From 1f824faa69205644599664793ded78ace8371e8c Mon Sep 17 00:00:00 2001 From: Deltik Date: Fri, 29 Mar 2019 19:13:32 -0500 Subject: [PATCH] Renormalized all text file line endings --- .gitignore | 38 +- README.md | 156 +- e107_admin/admin_log.php | 3778 ++-- e107_admin/cron.php | 2578 +-- e107_admin/emoticon.php | 1408 +- e107_admin/fileinspector.php | 3420 ++-- e107_admin/frontpage.php | 1506 +- e107_admin/update_routines.php | 4258 ++--- e107_admin/users.php | 5998 +++--- e107_core/bbcodes/b.bb | 8 +- e107_core/bbcodes/bb_block.php | 126 +- e107_core/bbcodes/bb_h.php | 150 +- e107_core/bbcodes/bb_nobr.php | 70 +- e107_core/bbcodes/bb_p.php | 140 +- e107_core/bbcodes/bb_youtube.php | 738 +- e107_core/bbcodes/blockquote.bb | 6 +- e107_core/bbcodes/center.bb | 8 +- e107_core/bbcodes/i.bb | 6 +- e107_core/bbcodes/justify.bb | 6 +- e107_core/bbcodes/sanitised.bb | 12 +- e107_core/bbcodes/u.bb | 4 +- e107_core/controllers/index/index.php | 370 +- e107_core/controllers/system/error.php | 124 +- e107_core/controllers/system/index.php | 46 +- e107_core/controllers/system/xup.php | 328 +- .../shortcodes/single/sitecontactinfo.sc | 2 +- e107_core/sql/extended_timezones.php | 298 +- e107_core/url/news/sef_full_url.php | 266 +- e107_core/url/news/sef_noid_url.php | 654 +- e107_core/url/news/sef_url.php | 418 +- e107_core/url/news/url.php | 416 +- e107_core/url/page/sef_noid_url.php | 302 +- e107_core/url/page/sef_url.php | 134 +- e107_core/url/page/url.php | 262 +- e107_core/url/search/rewrite_url.php | 100 +- e107_core/url/search/url.php | 134 +- e107_core/url/system/rewrite_url.php | 106 +- e107_core/url/system/url.php | 88 +- e107_core/url/user/rewrite_url.php | 204 +- e107_core/url/user/url.php | 260 +- e107_handlers/admin_log_class.php | 1852 +- e107_handlers/application.php | 9924 +++++----- e107_handlers/benchmark.php | 230 +- e107_handlers/e_marketplace.php | 2478 +-- e107_handlers/form_handler.php | 15330 ++++++++-------- e107_handlers/hybridauth/Hybrid/Auth.php | 828 +- e107_handlers/hybridauth/Hybrid/Error.php | 176 +- e107_handlers/hybridauth/Hybrid/Logger.php | 204 +- .../hybridauth/Hybrid/Provider_Adapter.php | 680 +- .../hybridauth/Hybrid/Provider_Model.php | 494 +- .../Hybrid/Provider_Model_OAuth1.php | 348 +- .../Hybrid/Provider_Model_OAuth2.php | 368 +- .../Hybrid/Provider_Model_OpenID.php | 340 +- .../hybridauth/Hybrid/Providers/AOL.php | 36 +- .../hybridauth/Hybrid/Providers/Facebook.php | 812 +- .../Hybrid/Providers/Foursquare.php | 242 +- .../hybridauth/Hybrid/Providers/Google.php | 612 +- .../Hybrid/Providers/GoogleOpenID.php | 80 +- .../hybridauth/Hybrid/Providers/LinkedIn.php | 340 +- .../hybridauth/Hybrid/Providers/Live.php | 200 +- .../hybridauth/Hybrid/Providers/MySpace.php | 328 +- .../hybridauth/Hybrid/Providers/OpenID.php | 32 +- .../hybridauth/Hybrid/Providers/Twitter.php | 528 +- .../hybridauth/Hybrid/Providers/Yahoo.php | 538 +- e107_handlers/hybridauth/Hybrid/Storage.php | 282 +- e107_handlers/hybridauth/Hybrid/User.php | 80 +- .../hybridauth/Hybrid/User_Activity.php | 110 +- .../hybridauth/Hybrid/User_Contact.php | 120 +- .../hybridauth/Hybrid/User_Profile.php | 326 +- e107_handlers/hybridauth/Hybrid/index.html | 18 +- .../Hybrid/resources/config.php.tpl | 144 +- .../hybridauth/Hybrid/resources/index.html | 18 +- .../Hybrid/resources/openid_policy.html | 18 +- .../Hybrid/resources/openid_realm.html | 26 +- .../Hybrid/resources/openid_xrds.xml | 22 +- .../resources/windows_live_channel.html | 72 +- .../Hybrid/thirdparty/LinkedIn/LinkedIn.php | 5446 +++--- .../Hybrid/thirdparty/OAuth/OAuth.php | 1802 +- .../WindowsLive/OAuthWrapHandler.php | 388 +- .../hybridauth/Hybrid/thirdparty/index.html | 18 +- e107_handlers/hybridauth/index.php | 32 +- e107_handlers/iphandler_class.php | 3350 ++-- e107_handlers/login.php | 1378 +- e107_handlers/mail.php | 2798 +-- e107_handlers/mail_template_class.php | 552 +- e107_handlers/media_class.php | 4568 ++--- e107_handlers/notify_class.php | 882 +- e107_handlers/pclzip.lib.php | 11392 ++++++------ e107_handlers/upload_handler.php | 2010 +- e107_handlers/user_extended_class.php | 2518 +-- e107_handlers/user_model.php | 5748 +++--- e107_languages/English/admin/help/mailout.php | 160 +- .../English/admin/lan_admin_log.php | 266 +- e107_languages/English/admin/lan_cron.php | 212 +- .../English/admin/lan_frontpage.php | 86 +- .../English/admin/lan_log_messages.php | 780 +- e107_languages/English/admin/lan_mailout.php | 596 +- .../English/admin/lan_userclass2.php | 222 +- .../English/admin/lan_validator.php | 94 +- e107_languages/English/lan_installer.php | 376 +- e107_plugins/alt_auth/alt_auth_adminmenu.php | 1166 +- e107_plugins/alt_auth/alt_auth_conf.php | 488 +- .../alt_auth/alt_auth_login_class.php | 590 +- e107_plugins/alt_auth/alt_auth_sql.php | 8 +- e107_plugins/alt_auth/e107db_auth.php | 394 +- e107_plugins/alt_auth/e107db_conf.php | 270 +- .../alt_auth/extended_password_handler.php | 768 +- e107_plugins/alt_auth/importdb_auth.php | 250 +- e107_plugins/alt_auth/importdb_conf.php | 210 +- .../languages/English/admin_e107db_conf.php | 78 +- .../languages/English/admin_ldap_conf.php | 88 +- .../languages/English/admin_radius_conf.php | 74 +- e107_plugins/alt_auth/ldap_auth.php | 618 +- e107_plugins/alt_auth/otherdb_auth.php | 410 +- e107_plugins/alt_auth/otherdb_conf.php | 274 +- e107_plugins/alt_auth/radius_auth.php | 500 +- e107_plugins/banner/banner_sql.php | 38 +- e107_plugins/chatbox_menu/admin_chatbox.php | 314 +- e107_plugins/chatbox_menu/chatbox_sql.php | 16 +- e107_plugins/chatbox_menu/e_notify.php | 112 +- .../languages/English/admin_chatbox_menu.php | 120 +- e107_plugins/download/download_sql.php | 152 +- .../languages/English/English_admin.php | 488 +- .../languages/English/English_log.php | 76 +- e107_plugins/faqs/controllers/e107.list.php | 284 +- e107_plugins/faqs/faqs_sql.php | 56 +- e107_plugins/featurebox/e_header.php | 18 +- e107_plugins/featurebox/featurebox.js | 254 +- e107_plugins/featurebox/featurebox_sql.php | 56 +- e107_plugins/forum/forum.php | 1750 +- e107_plugins/forum/forum_sql.php | 154 +- .../shortcodes/batch/forum_shortcodes.php | 1142 +- .../forum/templates/forum_template.php | 386 +- e107_plugins/gallery/controllers/index.php | 464 +- e107_plugins/gallery/css/gallery.css | 110 +- e107_plugins/gallery/e_header.php | 66 +- e107_plugins/gallery/e_shortcode.php | 720 +- e107_plugins/gallery/gallery.php | 338 +- .../languages/English/English_global.php | 28 +- e107_plugins/gallery/slideshow_menu.php | 88 +- .../gallery/templates/gallery_template.php | 390 +- e107_plugins/gallery/url/rewrite_url.php | 120 +- e107_plugins/gallery/url/url.php | 112 +- e107_plugins/gsitemap/gsitemap_sql.php | 24 +- e107_plugins/import/admin_import.php | 3378 ++-- .../import/languages/English_global.php | 18 +- e107_plugins/linkwords/linkwords_sql.php | 20 +- .../list_new/languages/English_global.php | 20 +- e107_plugins/log/admin_config.php | 2834 +-- e107_plugins/log/e_meta.php | 210 +- e107_plugins/log/log.php | 620 +- e107_plugins/log/log_sql.php | 12 +- e107_plugins/log/loginfo.php | 634 +- e107_plugins/news/news_months_menu.php | 284 +- .../news/templates/news_menu_template.php | 298 +- e107_plugins/newsfeed/newsfeed_sql.php | 24 +- e107_plugins/newsletter/e_mailout.php | 522 +- .../newsletter/newsletter_legacy_menu.php | 216 +- e107_plugins/newsletter/newsletter_sql.php | 24 +- e107_plugins/newsletter/nl_archive.php | 272 +- e107_plugins/pm/pm_menu.php | 316 +- e107_plugins/pm/pm_sql.php | 48 +- e107_plugins/poll/poll_sql.php | 34 +- e107_plugins/rss_menu/rss_sql.php | 24 +- e107_plugins/siteinfo/e_shortcode.php | 444 +- e107_plugins/trackback/trackback_sql.php | 20 +- e107_web/js/chap_script.js | 818 +- e107_web/js/core/admin.jquery.css | 90 +- e107_web/js/core/admin.jquery.js | 2198 +-- e107_web/js/core/all.jquery.css | 38 +- e107_web/js/core/all.jquery.js | 3702 ++-- e107_web/js/core/front.jquery.js | 944 +- e107_web/js/core/mediaManager.js | 1930 +- e107_web/js/plupload/upload.php | 70 +- e107_web/utilities/passconv.php | 594 +- e107_web/utilities/resetcore.php | 794 +- install.php | 4752 ++--- login.php | 250 +- thumb.php | 1086 +- top.php | 618 +- 180 files changed, 77527 insertions(+), 77527 deletions(-) diff --git a/.gitignore b/.gitignore index 1cb78b7cd..4ec907cd9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,19 @@ -# Ignore PhpStorm IDE files -.idea -.project -.htaccess -e107_config.php -e107_config_*.php -e107_media/* -e107_system/* -/.settings -e107_core/override -test/* -tmp/* -phpunit/ - -# Ignore Vim swap files -*.swp -*.swo -e107.htaccess -e107InstallLog.log +# Ignore PhpStorm IDE files +.idea +.project +.htaccess +e107_config.php +e107_config_*.php +e107_media/* +e107_system/* +/.settings +e107_core/override +test/* +tmp/* +phpunit/ + +# Ignore Vim swap files +*.swp +*.swo +e107.htaccess +e107InstallLog.log diff --git a/README.md b/README.md index 0f159a817..06e2f3859 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,78 @@ -## e107 [Content Management System][1] (CMS) - v2 - -[![Join the chat at https://gitter.im/e107inc/e107](https://badges.gitter.im/e107inc/e107.svg)](https://gitter.im/e107inc/e107?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -### What is e107? -e107 is a free (open-source) content management system which allows you to easily manage and publish your content online. Developers can save time in building websites and powerful online applications. Users can avoid programming completely! Blogs, Websites, Intranets - e107 does it all. - -### Requirements - - #### Minimum - - * A Web-Server (Apache or Microsoft IIS) running PHP v5.6 or higher and MySQL 4.x or 5.x. - * FTP access to your webserver and an FTP program such as Filezilla - * Username/Password to your MySQL Database - - #### Recommended - - * A Linux based Webserver running Apache 2.x, PHP 7.x and MySQL 5.x (LAMP) - * A registered Domain Name - * Access to a Server Control Panel (such as cPanel) - - -### Standard Installation - -* Unzip/Extract the compressed file onto your server. -* Point your browser to the *http://localhost/YOUR FOLDER/install.php* (depending on your webserver setup) -* Follow the installation wizard - - - -### Git Installation (developer version) - -* Run the following commands ( where 'youraccount' is the folder above your public_html folder and xxx:xxx is the default owner for your files - this can be found using FileZilla and FTP) -``` - cd youraccount - git clone https://github.com/e107inc/e107.git public_html - chown -R xxx:xxx public_html -``` -* Point your browser to the *http://localhost/YOUR FOLDER/install.php* (depending on your webserver setup) -* Follow the installation wizard - - - -### Reporting Bugs - -Be sure you are using the most recent version prior to reporting an issue. -You may report any bugs or feature requests on GitHub (https://github.com/e107inc/e107/issues) - - - -### Pull-Requests - -* Please submit 1 pull-request for each Github #issue you may work on. -* Make sure that only the lines you have changed actually show up in a file-comparison (diff) ie. some text-editors alter every line so this should be avoided. -* Make sure you are using rebase on your local .git/config file. -ie. [branch "master"] - rebase = true` -* Here's a small tutorial to give you a start on [CONTRIBUTING](CONTRIBUTING.md) - -### Donations -If you like e107 and wish to help it to improve - please consider making a small donation. - -* Bitcoin address: 18C7W2YvkzSjvPoW1y46PjkTdCr9UzC3F7 -* Paypal: donate (at) e107.org - - - -### Support -* http://e107help.org - - - -### License - -* e107 is released under the terms and conditions of the GNU General Public License (http://www.gnu.org/licenses/gpl.txt) - - [1]: http://e107.org - [2]: http://www.e107.org +## e107 [Content Management System][1] (CMS) - v2 + +[![Join the chat at https://gitter.im/e107inc/e107](https://badges.gitter.im/e107inc/e107.svg)](https://gitter.im/e107inc/e107?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +### What is e107? +e107 is a free (open-source) content management system which allows you to easily manage and publish your content online. Developers can save time in building websites and powerful online applications. Users can avoid programming completely! Blogs, Websites, Intranets - e107 does it all. + +### Requirements + + #### Minimum + + * A Web-Server (Apache or Microsoft IIS) running PHP v5.6 or higher and MySQL 4.x or 5.x. + * FTP access to your webserver and an FTP program such as Filezilla + * Username/Password to your MySQL Database + + #### Recommended + + * A Linux based Webserver running Apache 2.x, PHP 7.x and MySQL 5.x (LAMP) + * A registered Domain Name + * Access to a Server Control Panel (such as cPanel) + + +### Standard Installation + +* Unzip/Extract the compressed file onto your server. +* Point your browser to the *http://localhost/YOUR FOLDER/install.php* (depending on your webserver setup) +* Follow the installation wizard + + + +### Git Installation (developer version) + +* Run the following commands ( where 'youraccount' is the folder above your public_html folder and xxx:xxx is the default owner for your files - this can be found using FileZilla and FTP) +``` + cd youraccount + git clone https://github.com/e107inc/e107.git public_html + chown -R xxx:xxx public_html +``` +* Point your browser to the *http://localhost/YOUR FOLDER/install.php* (depending on your webserver setup) +* Follow the installation wizard + + + +### Reporting Bugs + +Be sure you are using the most recent version prior to reporting an issue. +You may report any bugs or feature requests on GitHub (https://github.com/e107inc/e107/issues) + + + +### Pull-Requests + +* Please submit 1 pull-request for each Github #issue you may work on. +* Make sure that only the lines you have changed actually show up in a file-comparison (diff) ie. some text-editors alter every line so this should be avoided. +* Make sure you are using rebase on your local .git/config file. +ie. [branch "master"] + rebase = true` +* Here's a small tutorial to give you a start on [CONTRIBUTING](CONTRIBUTING.md) + +### Donations +If you like e107 and wish to help it to improve - please consider making a small donation. + +* Bitcoin address: 18C7W2YvkzSjvPoW1y46PjkTdCr9UzC3F7 +* Paypal: donate (at) e107.org + + + +### Support +* http://e107help.org + + + +### License + +* e107 is released under the terms and conditions of the GNU General Public License (http://www.gnu.org/licenses/gpl.txt) + + [1]: http://e107.org + [2]: http://www.e107.org diff --git a/e107_admin/admin_log.php b/e107_admin/admin_log.php index df7eee885..908c4d200 100644 --- a/e107_admin/admin_log.php +++ b/e107_admin/admin_log.php @@ -1,1889 +1,1889 @@ - $file) - { - $file = str_replace('--LAN--', e_LANGUAGE, $file); - - // echo "orig = ".$file." "; - //e107::lan($path,'log',true); - e107::includeLan(e_PLUGIN.$path.'/languages/'.$file); - } -} - -define('AL_DATE_TIME_FORMAT', 'y-m-d H:i:s'); - - - -class adminlog_admin extends e_admin_dispatcher -{ - - protected $modes = array( - - 'main' => array( - 'controller' => 'admin_log_ui', - 'path' => null, - 'ui' => 'admin_log_form_ui', - 'uipath' => null - ), - - - 'audit' => array( - 'controller' => 'audit_log_ui', - 'path' => null, - 'ui' => 'admin_log_form_ui', - 'uipath' => null - ), - - - 'rolling' => array( - 'controller' => 'dblog_ui', - 'path' => null, - 'ui' => 'admin_log_form_ui', - 'uipath' => null - ), - - - ); - - //$page_title = array('adminlog' => RL_LAN_030, 'auditlog' => RL_LAN_062, 'rolllog' => RL_LAN_002, 'downlog' => RL_LAN_067, 'detailed' => RL_LAN_094, 'online' => RL_LAN_120); - - - protected $adminMenu = array( - - 'main/list' => array('caption'=> RL_LAN_030, 'perm' => '5'), - 'audit/list' => array('caption'=> RL_LAN_062, 'perm' => '5'), - 'rolling/list' => array('caption'=> RL_LAN_002, 'perm' => '5'), - 'divider/01' => array('divider'=>true), - 'main/prefs' => array('caption'=> LAN_PREFS, 'perm' => '5'), - 'main/maintenance' => array('caption'=> LAN_OPTIONS, 'perm' => '5') - - // 'main/custom' => array('caption'=> 'Custom Page', 'perm' => 'P') - ); - - protected $adminMenuAliases = array( - 'main/edit' => 'main/list' - ); - - protected $adminMenuIcon = 'e-adminlogs-24'; - - protected $menuTitle = ADLAN_155; - - function init() - { - - e107::css('inline', " - - .fa { font-size:130% } - .fa-question-circle { } - .fa-exclamation-circle { color: #FAA732 } - .fa-warning { color: red } - - - - "); - - - } -} - - - - - -class admin_log_ui extends e_admin_ui -{ - - protected $pluginTitle = ADLAN_155; - protected $pluginName = 'core'; - protected $table = 'admin_log'; - protected $pid = 'dblog_id'; - protected $perPage = 10; - // protected $listQry = "SELECT f.*, u.* FROM #admin_log AS f LEFT JOIN #user AS u ON f.dblog_user_id = u.user_id "; // Should not be necessary. - - protected $listQry = "SELECT SQL_CALC_FOUND_ROWS f.*, u.user_id, u.user_name FROM #admin_log AS f LEFT JOIN #user AS u ON f.dblog_user_id = u.user_id "; // Should not be required but be auto-calculated. - protected $listOrder = 'f.dblog_id DESC'; - - protected $batchDelete = false; - protected $batchDeleteLog = false; //TODO - AdminUI option to disable logging of changes. - - protected $fields = array ( - // 'checkboxes' => array ( 'title' => '', 'type' => null, 'data' => null, 'nolist'=>true, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect', ), - 'dblog_id' => array ( 'title' => LAN_ID, 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_datestamp' => array ( 'title' => LAN_DATESTAMP, 'type' => 'datestamp', 'data' => 'int', 'width' => '12%', 'filter' => true, 'help' => '', 'readParms' => array('mask'=>'dd MM yyyy hh:ii:ss'), 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - // 'dblog_microtime' => array ( 'title' => 'Microtime', 'type' => 'method', 'data' => 'int', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), - 'dblog_type' => array ( 'title' => RL_LAN_032, 'type' => 'method', 'data' => 'int', 'width' => '5%', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), - 'dblog_ip' => array ( 'title' => LAN_IP, 'type' => 'ip', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - - 'dblog_user_id' => array ( 'title' => LAN_USER, 'type' => 'user', 'data' => 'int', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms'=>'link=1', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_eventcode' => array ( 'title' => RL_LAN_023, 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - - 'dblog_title' => array ( 'title' => LAN_TITLE, 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_remarks' => array ( 'title' => RL_LAN_033, 'type' => 'method', 'data' => 'str', 'width' => '35%', 'filter'=>true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'options' => array ( 'title' => LAN_OPTIONS, 'type' => null, 'nolist'=>true, 'data' => null, 'width' => '10%', 'thclass' => 'center last', 'class' => 'center last', 'forced' => '1', ), - ); - - protected $fieldpref = array( 'dblog_datestamp', 'dblog_type', 'dblog_eventcode', 'dblog_user_id', 'dblog_ip', 'dblog_title', 'dblog_remarks'); - - //'adminlog' => array(RL_LAN_019, RL_LAN_032, RL_LAN_020, RL_LAN_104, LAN_USER, RL_LAN_023, LAN_TITLE, RL_LAN_033), - - - protected $prefs = array( - 'sys_log_perpage' => array('title'=> RL_LAN_044, 'type'=>'dropdown', 'data' => 'int','help'=> RL_LAN_064,'writeParms'=>''), - 'user_audit_class' => array('title'=> RL_LAN_123, 'type'=>'userclass', 'data' => 'int','help'=>''), - 'user_audit_opts' => array('title'=> RL_LAN_031, 'type'=>'method', 'data' => 'array','help'=>''), - 'roll_log_active' => array('title'=> RL_LAN_008, 'type'=>'boolean', 'data' => 'int','help'=>''), - 'roll_log_days' => array('title'=> RL_LAN_009, 'type'=>'number', 'data' => 'string','help'=>''), - // 'Delete admin log events older than ' => array('title'=> RL_LAN_045, 'type'=>'method', 'data' => 'string','help'=>'Help Text goes here'), - // 'Delete user audit trail log events older' => array('title'=> 'Delete user audit trail log events older', 'type'=>'method', 'data' => 'string','help'=>'Help Text goes here'), - ); - - - - - - - - - - - - - - - - - public $eventTypes = array(); - - // optional - public function init() - { - $perPage = e107::getConfig()->get('sys_log_perpage'); - $this->perPage = vartrue($perPage,10); - - $this->prefs['sys_log_perpage']['writeParms'] = array(10=>10, 15=>15, 20=>20, 30=>30, 40=>40, 50=>50); - - - $sql = e107::getDb(); - $row = $sql->retrieve("SELECT dblog_eventcode,dblog_title FROM #admin_log WHERE dblog_eventcode !='' AND dblog_title !='' GROUP BY dblog_eventcode",true); - foreach($row as $val) - { - $id = $val['dblog_eventcode']; - $def = strpos($val['dblog_title'], "LAN") !== false ? $id : $val['dblog_title']; - $this->eventTypes[$id] = str_replace(': [x]', '', deftrue($val['dblog_title'],$def)); - } - - asort($this->eventTypes); - - if(getperms('0')) - { - - $arr = array_reverse($this->fields, true); - $arr['checkboxes'] = array ( 'title' => '', 'type' => null, 'data' => null, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect' ); - - $this->fields = array_reverse($arr, true); - $this->batchDelete = true; - } - } - - - function gen_log_delete($selectname) - { - $values = array(360, 180, 90, 60, 30, 21, 20, 14, 10, 7, 6, 5, 4, 3, 2, 1); - return e107::getForm()->select($selectname, $values, '', 'useValues=1&size=small'); - } - - - function maintenancePage() - { - - if(!empty($_POST['deleteoldadmin']) || !empty($_POST['deleteoldaudit'])) - { - $this->maintenanceProcess(); - - } - - $frm = e107::getForm(); - - - - // Admin log maintenance - //================== - $text = " -
-
- ".RL_LAN_125." - - - - - - - - - - - "; - - // User log maintenance - //==================== - $text .= " - - - - - -
".RL_LAN_045." ".$this->gen_log_delete('rolllog_clearadmin')." ".RL_LAN_046." ".$frm->admin_button('deleteoldadmin', 'no-value', 'delete', RL_LAN_049)."
".RL_LAN_066." ".$this->gen_log_delete('rolllog_clearaudit')." ".RL_LAN_046." ".$frm->admin_button('deleteoldaudit', 'no-value', 'delete', RL_LAN_049)."
-
-
- - - "; - return $text; - - } - - - function maintenanceProcess() - { - $mes = e107::getMessage(); - $ns = e107::getRender(); - $log = e107::getAdminLog(); - $frm = e107::getForm(); - $sql = e107::getDb(); - - // print_a($_POST); - - if(!empty($_POST['deleteoldadmin']) && isset($_POST['rolllog_clearadmin'])) - { - $back_count = intval($_POST['rolllog_clearadmin']); - $_POST['backdeltype'] = 'confdel'; - $action = 'backdel'; - } - elseif(!empty($_POST['deleteoldaudit']) && isset($_POST['rolllog_clearaudit'])) - { - $back_count = intval($_POST['rolllog_clearaudit']); - $action = 'backdel'; - $_POST['backdeltype'] = 'auditdel'; - } - - /* - if(isset($back_count)) - { - if(($back_count >= 1) && ($back_count <= 90)) - { - $temp_date = getdate(); - $old_date = intval(mktime(0, 0, 0, $temp_date['mon'], $temp_date['mday'] - $back_count, $temp_date['year'])); - $old_string = strftime("%d %B %Y", $old_date); - // $message = "Back delete ".$back_count." days. Oldest date = ".$old_string; - $action = $next_action; - $qs[1] = $old_date; - $qs[2] = $back_count; - } - else - { - $mes->addWarning(RL_LAN_050); - } - } - */ - - $old_date = strtotime($back_count.' days ago'); - - - // Actually delete back events - admin or user audit log - if(($action == "backdel") && isset($_POST['backdeltype'])) - { - // $old_date = intval($qs[1]); - $old_string = strftime("%d %B %Y", $old_date); - $qry = "dblog_datestamp < ".$old_date; // Same field for both logs - - switch($_POST['backdeltype']) - { - case 'confdel': - $db_table = 'admin_log'; - $db_name = RL_LAN_052; - $db_msg = "ADLOG_02"; - break; - case 'auditdel': - $db_table = 'audit_log'; - $db_name = RL_LAN_053; - $db_msg = "ADLOG_03"; - break; - default: - exit(); // Someone fooling around! - } - - - e107::getMessage()->addDebug("Back delete,
oldest date = {$old_string}
Query = {$qry}"); - - if($del_count = $sql->delete($db_table, $qry)) - { - // Add in a log event - $message = $db_name.str_replace(array('[x]', '[y]'), array($old_string, $del_count), RL_LAN_057); - $mes->addSuccess($message); - $log->log_event($db_msg, "db_Delete - earlier than {$old_string} (past {$back_count} days)[!br!]".$message.'[!br!]'.$db_table.' '.$qry, E_LOG_INFORMATIVE, ''); - } - else - { - $mes->addWarning(RL_LAN_054." : ".$sql->mySQLresult); - } - - } - - // Prompt to delete back events - /* - if(($action == "confdel") || ($action == "auditdel")) - { - $old_string = strftime("%d %B %Y", $qs[1]); - $text = " -
-
- ".LAN_CONFDELETE." - - - - -
- ".(($action == "confdel") ? RL_LAN_047 : RL_LAN_065).$old_string." -
-
- - ".$frm->admin_button('confirmdeleteold', 'no-value', 'delete', RL_LAN_049)." - ".$frm->admin_button('confirmcancelold', 'no-value', 'delete', LAN_CANCEL)." -
-
-
- - "; - - $ns->tablerender(LAN_CONFDELETE, $text); - } - - */ - - } - - - -} - - -class admin_log_form_ui extends e_admin_form_ui -{ - - function sys_log_perpage($curVal,$mode) - { - $frm = e107::getForm(); - switch($mode) - { - case 'write': // Edit Page - return $frm->text('sys_log_perpage',$curVal); - break; - } - } - - function user_audit_opts($curVal,$mode) - { - - $frm = e107::getForm(); - - // User Audit log options (for info) - //======================= - // define('USER_AUDIT_SIGNUP',11); // User signed up - // define('USER_AUDIT_EMAILACK',12); // User responded to registration email - // define('USER_AUDIT_LOGIN',13); // User logged in - // define('USER_AUDIT_LOGOUT',14); // User logged out - // define('USER_AUDIT_NEW_DN',15); // User changed display name - // define('USER_AUDIT_NEW_PW',16); // User changed password - // define('USER_AUDIT_NEW_EML',17); // User changed email - // define('USER_AUDIT_NEW_SET',19); // User changed other settings (intentional gap in numbering) - // define('USER_AUDIT_ADD_ADMIN', 20); // User added by admin - // define('USER_AUDIT_MAIL_BOUNCE', 21); // User mail bounce - // define('USER_AUDIT_BANNED', 22); // User banned - // define('USER_AUDIT_BOUNCE_RESET', 23); // User bounce reset - // define('USER_AUDIT_TEMP_ACCOUNT', 24); // User temporary account - - - $audit_checkboxes = array(USER_AUDIT_SIGNUP => RL_LAN_071, USER_AUDIT_EMAILACK => RL_LAN_072, - USER_AUDIT_LOGIN => LAN_AUDIT_LOG_013, USER_AUDIT_LOGOUT => LAN_AUDIT_LOG_014, // Logout is lumped in with login - USER_AUDIT_NEW_DN => RL_LAN_075, USER_AUDIT_NEW_PW => RL_LAN_076, USER_AUDIT_PW_RES => RL_LAN_078, USER_AUDIT_NEW_EML => RL_LAN_077, USER_AUDIT_NEW_SET => RL_LAN_079, - USER_AUDIT_ADD_ADMIN => RL_LAN_080, USER_AUDIT_MAIL_BOUNCE => RL_LAN_081, USER_AUDIT_BANNED => RL_LAN_082, USER_AUDIT_BOUNCE_RESET => RL_LAN_083, - USER_AUDIT_TEMP_ACCOUNT => RL_LAN_084); - - $userAuditOpts = e107::getConfig()->get('user_audit_opts'); - - $text = ""; - - foreach($audit_checkboxes as $k => $t) - { - $checked = isset($userAuditOpts[$k]) ? true : false; - $text .= $frm->checkbox('user_audit_opts['.$k.']',$k, $checked, array('label'=>$t)); - } - - $text .= $frm->admin_button('check_all', 'jstarget:user_audit_opts', 'checkall', LAN_CHECKALL).$frm->admin_button('uncheck_all', 'jstarget:user_audit_opts', 'checkall', LAN_UNCHECKALL); - - - return $text; - } - - - - - // Custom Method/Function - /* - function dblog_datestamp($curVal,$mode) - { - $frm = e107::getForm(); - - switch($mode) - { - case 'read': // List Page - return date(AL_DATE_TIME_FORMAT, $curVal); - break; - - case 'write': // Edit Page - return $frm->text('dblog_datestamp',$curVal); - break; - - case 'filter': - case 'batch': - return $array; - break; - } - } - */ - - // Custom Method/Function - function dblog_microtime($curVal,$mode) - { - $frm = e107::getForm(); - - switch($mode) - { - case 'read': // List Page - return date("H:i:s", intval($curVal) % 86400).'.'.str_pad(100000 * round($curVal - floor($curVal), 6), 6, '0'); - break; - - case 'write': // Edit Page - return $frm->text('dblog_microtime',$curVal); - break; - - case 'filter': - case 'batch': - return $array; - break; - } - } - - - // Custom Method/Function - function dblog_type($curVal,$mode) - { - $tp = e107::getParser(); - /* - define("E_LOG_INFORMATIVE", 0); // Minimal Log Level, including really minor stuff - define("E_LOG_NOTICE", 1); // More important than informative, but less important than notice - define("E_LOG_WARNING", 2); // Not anything serious, but important information - define("E_LOG_FATAL", 3); // An event so bad your site ceased execution. - define("E_LOG_PLUGIN", 4); // Plugin information - */ - - $array = array( - ' ', // Minimal Log Level, including really minor stuff - '', //FIXME - should be the blue icon. // More important than informative, but less important than notice - '', // Not anything serious, but important information - '', // An event so bad your site ceased execution. - ' ' // Plugin information - Deprecated - Leave empty. - ); - - $array[1] = $tp->toGlyph('fa-question-circle'); - $array[2] = $tp->toGlyph('fa-exclamation-circle'); - $array[3] = $tp->toGlyph('fa-warning'); - - switch($mode) - { - case 'read': // List Page - return varset($array[$curVal], $curVal); - break; - - case 'filter': - case 'batch': - return array(RL_LAN_132,RL_LAN_133,RL_LAN_134,RL_LAN_135); - break; - } - } - - - - // Custom Method/Function - function dblog_title($curVal,$mode) - { - $tp = e107::getParser(); - - switch($mode) - { - case 'read': // List Page - - - - $val = trim($curVal); - if(defined($val)) - { - $val = constant($val); - } - - if(strpos($val,'[x]') !== false) - { - $remark = $this->getController()->getListModel()->get('dblog_remarks'); - preg_match("/\[table\]\s=>\s([\w]*)/i",$remark, $match); - - if(!empty($match[1])) - { - $val = $tp->lanVars($val, ''.$match[1].''); - } - else - { - preg_match("/\[!br!\]TABLE: ([\w]*)/i", $remark, $m); - if(!empty($m[1])) - { - $val = $tp->lanVars($val, ''.$m[1].''); - } - } - - - } - - return $val; - break; - - case 'filter': - case 'batch': - return null; - break; - } - } - - - function dblog_eventcode($curVal,$mode) - { - $array = $this->getController()->eventTypes; - - switch($mode) - { - case 'read': // List Page - return $curVal; - break; - - case 'filter': - case 'batch': - return $array; - break; - } - } - - - // Custom Method/Function - function dblog_remarks($curVal,$mode) - { - $frm = e107::getForm(); - $tp = e107::getParser(); - - switch($mode) - { - case 'read': // List Page - - $text = preg_replace_callback("#\[!(\w+?)(=.+?){0,1}!]#", 'log_process', $curVal); - $text = $tp->toHTML($text,false,'E_BODY'); - - if(strpos($text,'Array')!==false || strlen($text)>300) - { - $id = $this->getController()->getListModel()->get('dblog_id'); - $ret ="".RL_LAN_087.""; - $ret .= ""; - return $ret; - } - - return $text; - break; - - - case 'filter': - case 'batch': - return $array; - break; - } - } - -// Custom Method/Function - function dblog_caller($curVal,$mode) - { - - switch($mode) - { - case 'read': // List Page - $val =$curVal; - if((strpos($val, '|') !== FALSE) && (strpos($val, '@') !== FALSE)) - { - list($file, $rest) = explode('|', $val); - list($routine, $rest) = explode('@', $rest); - $val = $file.'
Function: '.$routine.'
Line: '.$rest; - } - return $val; - break; - - - case 'filter': - case 'batch': - return $array; - break; - } - } - -} - - - -class audit_log_ui extends e_admin_ui -{ - - protected $pluginTitle = ADLAN_155; - protected $pluginName = 'adminlog'; - protected $table = 'audit_log'; - protected $pid = 'dblog_id'; - protected $perPage = 10; - protected $listOrder = 'dblog_id DESC'; - protected $batchDelete = true; - - protected $fields = array ( - 'checkboxes' => array ( 'title' => '', 'type' => null, 'data' => null, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect', ), - 'dblog_id' => array ( 'title' => LAN_ID, 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_datestamp' => array ( 'title' => LAN_DATESTAMP, 'type' => 'datestamp', 'data' => 'int', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => array('mask'=>'dd MM yyyy hh:ii:ss'), 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_microtime' => array ( 'title' => 'Microtime', 'type' => 'text', 'data' => 'int', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), - 'dblog_eventcode' => array ( 'title' => 'Eventcode', 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), - 'dblog_user_id' => array ( 'title' => LAN_USER, 'type' => 'user', 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_user_name' => array ( 'title' => LAN_USER, 'type' => 'text', 'data' => 'str', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_ip' => array ( 'title' => LAN_IP, 'type' => 'ip', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_title' => array ( 'title' => LAN_TITLE, 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_remarks' => array ( 'title' => 'Remarks', 'type' => 'method', 'data' => 'str', 'width' => '30%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'options' => array ( 'title' => LAN_OPTIONS, 'type' => null, 'nolist'=>true, 'data' => null, 'width' => '10%', 'thclass' => 'center last', 'class' => 'center last', 'forced' => '1', ), - ); - - protected $fieldpref = array('dblog_id', 'dblog_datestamp', 'dblog_microtime', 'dblog_eventcode', 'dblog_user_id', 'dblog_user_name', 'dblog_ip', 'dblog_title','dblog_remarks'); - - - - // optional - public function init() - { - $perPage = e107::getConfig()->get('sys_log_perpage'); - $this->perPage = vartrue($perPage,10); - } - - /* - public function customPage() - { - $ns = e107::getRender(); - $text = 'Hello World!'; - $ns->tablerender('Hello',$text); - - } - */ - -} - - - - - - - -class dblog_ui extends e_admin_ui -{ - - protected $pluginTitle = ADLAN_155; - protected $pluginName = 'adminlog'; - protected $table = 'dblog'; - protected $pid = 'dblog_id'; - protected $perPage = 15; - protected $listOrder = 'dblog_id desc'; - - protected $fields = array ( - 'checkboxes' => array ( 'title' => '', 'type' => null, 'data' => null, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect', ), - // 'dblog_id' => array ( 'title' => LAN_ID, 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_datestamp' => array ( 'title' => LAN_DATESTAMP, 'type' => 'datestamp', 'data' => 'int', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => array('mask'=>'dd MM yyyy hh:ii:ss'), 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_microtime' => array ( 'title' => 'Microtime', 'type' => 'method', 'data' => 'int', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), - 'dblog_type' => array ( 'title' => LAN_TYPE, 'type' => 'method', 'data' => 'int', 'width' => 'auto', 'batch' => true, 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_eventcode' => array ( 'title' => 'Eventcode', 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), - 'dblog_user_id' => array ( 'title' => LAN_ID, 'type' => 'user', 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_user_name' => array ( 'title' => LAN_USER, 'type' => 'text', 'data' => 'str', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_ip' => array ( 'title' => LAN_IP, 'type' => 'ip', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_caller' => array ( 'title' => 'Caller', 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), - 'dblog_title' => array ( 'title' => LAN_TITLE, 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'dblog_remarks' => array ( 'title' => 'Remarks', 'type' => 'method', 'data' => 'str', 'width' => '30%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'options' => array ( 'title' => LAN_OPTIONS, 'type' => null, 'nolist'=>true, 'data' => null, 'width' => '10%', 'thclass' => 'center last', 'class' => 'center last', 'forced' => '1', ), - ); - - protected $fieldpref = array('dblog_id', 'dblog_datestamp', 'dblog_microtime', 'dblog_type', 'dblog_eventcode', 'dblog_user_id', 'dblog_user_name', 'dblog_ip', 'dblog_caller', 'dblog_title', 'dblog_remarks'); - - - // optional - public function init() - { - $perPage = e107::getConfig()->get('sys_log_perpage'); - $this->perPage = vartrue($perPage,10); - } - -} - - - - -// Routine to handle the simple bbcode-like codes for log body text - - function log_process($matches) - { - switch($matches[1]) - { - case 'br': - return '
'; - case 'link': - $temp = substr($matches[2], 1); - return "{$temp}"; - case 'test': - return '----TEST----'; - default: - return $matches[0]; // No change - } - } - - - - - - -new adminlog_admin(); - -require_once(e_ADMIN."auth.php"); -e107::getAdminUI()->runPage(); - -require_once(e_ADMIN."footer.php"); -exit; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Everything below this point is currently unused, but left for reference in case of bugs. -// ---------------------------------------------------------------------------------------------------------- - - - - - - - - -if(is_array($pref['lan_log_list'])) //... and for any plugins which support it -{ - foreach($pref['lan_log_list'] as $path => $file) - { - $file = str_replace('--LAN--', e_LANGUAGE, $file); - - // echo "orig = ".$file." "; - //e107::lan($path,'log',true); - e107::includeLan(e_PLUGIN.$path.'/languages/'.$file); - } -} - -unset($qs); - -require_once (e_ADMIN.'auth.php'); - -$mes = e107::getMessage(); -$frm = e107::getForm(); - -define('AL_DATE_TIME_FORMAT', 'y-m-d H:i:s'); -/* -if(isset($_POST['setoptions'])) -{ - unset($temp); - - if(in_array((string) USER_AUDIT_LOGIN, $_POST['user_audit_opts'])) - { - $_POST['user_audit_opts'][] = USER_AUDIT_LOGOUT; - } - foreach($_POST['user_audit_opts'] as $k => $v) - { - if(! is_numeric($v)) - { - unset($_POST['user_audit_opts'][$k]); - } - } - $temp['roll_log_active'] = intval($_POST['roll_log_active']); - $temp['roll_log_days'] = intval($_POST['roll_log_days']); - $temp['sys_log_perpage'] = intval($_POST['sys_log_perpage']); - $temp['user_audit_opts'] = implode(',', $_POST['user_audit_opts']); - $temp['user_audit_class'] = intval($_POST['user_audit_class']); - - if($admin_log->logArrayDiffs($temp, $pref, 'ADLOG_01') || $admin_log->logArrayDiffs($temp, $pref, 'ADLOG_04')) - { - save_prefs(); // Only save if changes - } - else - { - $mes->addInfo(LAN_NO_CHANGE); - } - -} -*/ - -$ns->tablerender($caption, $mes->render() . $text); - -if(e_QUERY) -{ // Must explode after calling auth.php - $qs = explode(".", e_QUERY); -} - -$action = varset($qs[0], 'adminlog'); - -// Deprecated by Comments Manager -/* -if(isset($_POST['deleteitems']) && ($action == 'comments')) -{ - $c_list = array(); - foreach($_POST['del_item'] as $di) - { - if(intval($di) > 0) - $c_list[] = '`comment_id`='.intval($di); - } - if($count = $sql->db_Delete('comments', implode(' OR ', $c_list))) - { - //$text = str_replace('--NUMBER--', $count,RL_LAN_112); - $emessage->add(str_replace('--NUMBER--', $count, RL_LAN_112), E_MESSAGE_SUCCESS); - e107::getLog()->add('COMMENT_01', 'ID: '.implode(',', $_POST['del_item']), E_LOG_INFORMATIVE, ''); - } - else - { - //$text = RL_LAN_113; - $emessage->add(RL_LAN_113, E_MESSAGE_WARNING); - } - //$ns -> tablerender(LAN_DELETE, "
".$text."
"); - unset($c_list); -} -*/ - -// ****************** MAINTENANCE ****************** -unset($back_count); -if(isset($_POST['deleteoldadmin']) && isset($_POST['rolllog_clearadmin'])) -{ - $back_count = intval($_POST['rolllog_clearadmin']); - $next_action = 'confdel'; -} -elseif(isset($_POST['deleteoldaudit']) && isset($_POST['rolllog_clearaudit'])) -{ - $back_count = intval($_POST['rolllog_clearaudit']); - $next_action = 'auditdel'; -} - -if(isset($back_count) && isset($next_action)) -{ - if(($back_count >= 1) && ($back_count <= 90)) - { - $temp_date = getdate(); - $old_date = intval(mktime(0, 0, 0, $temp_date['mon'], $temp_date['mday'] - $back_count, $temp_date['year'])); - $old_string = strftime("%d %B %Y", $old_date); - // $message = "Back delete ".$back_count." days. Oldest date = ".$old_string; - $action = $next_action; - $qs[1] = $old_date; - $qs[2] = $back_count; - } - else - { - $mes->addWarning(RL_LAN_050); - } -} - -if(!isset($admin_log)) -{ - $mes->addWarning("Admin Log not valid"); -} - - -// Actually delete back events - admin or user audit log -if(($action == "backdel") && isset($_POST['backdeltype'])) -{ - if(isset($_POST['confirmdeleteold'])) - { - $old_date = intval($qs[1]); - $old_string = strftime("%d %B %Y", $old_date); - $qry = "dblog_datestamp < ".$old_date; // Same field for both logs - switch($_POST['backdeltype']) - { - case 'confdel': - $db_table = 'admin_log'; - $db_name = RL_LAN_052; - $db_msg = "ADLOG_02"; - break; - case 'auditdel': - $db_table = 'audit_log'; - $db_name = RL_LAN_053; - $db_msg = "ADLOG_03"; - break; - default: - exit(); // Someone fooling around! - } - // $message = "Back delete, oldest date = {$old_string} Query = {$qry}"; - if($del_count = $sql->db_Delete($db_table, $qry)) - { - // Add in a log event - $message = $db_name.str_replace(array('[x]', '[y]'), array($old_string, $del_count), RL_LAN_057); - $mes->addSuccess($message); - e107::getLog()->add($db_msg, "db_Delete - earlier than {$old_string} (past {$qs[2]} days)[!br!]".$message.'[!br!]'.$db_table.' '.$qry, E_LOG_INFORMATIVE, ''); - } - else - { - $mes->addWarning(RL_LAN_054." : ".$sql->mySQLresult); - } - } - else - { - $mes->addInfo(LAN_NO_CHANGE); - } - - $action = "config"; - unset($qs[1]); - unset($qs[2]); -} - -// Prompt to delete back events -if(($action == "confdel") || ($action == "auditdel")) -{ - $old_string = strftime("%d %B %Y", $qs[1]); - $text = " -
-
- ".LAN_CONFDELETE." - - - - -
- ".(($action == "confdel") ? RL_LAN_047 : RL_LAN_065).$old_string." -
-
- - ".$frm->admin_button('confirmdeleteold', 'no-value', 'delete', RL_LAN_049)." - ".$frm->admin_button('confirmcancelold', 'no-value', 'delete', LAN_CANCEL)." -
-
-
- - "; - - $ns->tablerender(LAN_CONFDELETE, $text); -} - -// Arrays of options for the various logs - the $page_title array is used to determine the allowable values for $action ('options' is a special case) -$log_db_table = array('adminlog' => 'admin_log', 'auditlog' => 'audit_log', 'rolllog' => 'dblog', 'downlog' => 'download_requests', 'online' => 'online'); -$back_day_count = array('adminlog' => 30, 'auditlog' => 30, 'rolllog' => max(intval($pref['roll_log_days']), 1), 'downlog' => 60, 'detailed' => 20, 'online' => 30); -$page_title = array('adminlog' => RL_LAN_030, 'auditlog' => RL_LAN_062, 'rolllog' => RL_LAN_002, 'downlog' => RL_LAN_067, 'detailed' => RL_LAN_094, 'online' => RL_LAN_120); - -// Set all the defaults for the data filter -$start_enabled = FALSE; -$end_enabled = FALSE; -$start_time = 0; -$end_time = 0; -$user_filter = ''; -$event_filter = ''; -$pri_filter_cond = "xx"; -$pri_filter_val = ""; -$sort_order = "DESC"; -$downloadid_filter = ''; - -$last_noted_time = 0; - -// Maintain the log view filter across pages -$rl_cookiename = $pref['cookie_name']."_rl_admin"; -if(isset($_POST['updatefilters']) || isset($_POST['clearfilters'])) -{ // Need to put the filter values into the cookie - if(! isset($_POST['clearfilters'])) - { // Only update filter values from $_POST[] if 'clear filters' not active - $start_time = intval($_POST['starttimedate'] + $_POST['starttimehours'] * 3600 + $_POST['starttimemins'] * 60); - $start_enabled = isset($_POST['start_enabled']); - if(isset($_POST['timelength'])) - { - $end_time = intval($_POST['timelength']) * 60 + $start_time; - } - else - { - $end_time = intval($_POST['endtimedate'] + $_POST['endtimehours'] * 3600 + $_POST['endtimemins'] * 60); - } - $end_enabled = isset($_POST['end_enabled']); - $user_filter = trim(varset($_POST['roll_user_filter'], '')); - if($user_filter != '') - $user_filter = intval($user_filter); - $event_filter = $tp->toDB($_POST['roll_event_filter']); - $pri_filter_cond = $tp->toDB($_POST['roll_pri_cond']); - $pri_filter_val = $tp->toDB($_POST['roll_pri_val']); - $caller_filter = $tp->toDB($_POST['roll_caller_filter']); - $ipaddress_filter = $e107->ipEncode($tp->toDB($_POST['roll_ipaddress_filter'])); - $downloadid_filter = $tp->toDB($_POST['roll_downloadid_filter']); - } - $cookie_string = implode("|", array($start_time, $start_enabled, $end_time, $end_enabled, $user_filter, $event_filter, $pri_filter_cond, $pri_filter_val, $caller_filter, $ipaddress_filter, $downloadid_filter)); - // echo $cookie_string."
"; - // Create session cookie to store values - cookie($rl_cookiename, $cookie_string, 0); // Use session cookie -} -else -{ - // Now try and get the filters from the cookie - if(isset($_COOKIE[$rl_cookiename])) - list($start_time, $start_enabled, $end_time, $end_enabled, $user_filter, $event_filter, $pri_filter_cond, $pri_filter_val, $caller_filter, $ipaddress_filter, $downloadid_filter) = explode("|", $_COOKIE[$rl_cookiename]); - if(isset($qs[1]) && isset($qs[2]) && ($qs[1] == 'user') && (intval($qs[2]) > 0)) - { - $user_filter = intval($qs[2]); - } -} - -$timelength = 5; -if($start_time != 0 && $end_time != 0) - $timelength = intval(($end_time - $start_time) / 60); - -function time_box($boxname, $this_time, $day_count, $inc_tomorrow = FALSE, $all_mins = FALSE) -{ // Generates boxes for date and time for today and the preceding days - // Appends 'date', 'hours', 'mins' to the specified boxname - - - $all_time = getdate(); // Date/time now - $sel_time = getdate($this_time); // Currently selected date/time - $sel_day = mktime(0, 0, 0, $sel_time['mon'], $sel_time['mday'], $sel_time['year']); - $today = mktime(0, 0, 0, $all_time['mon'], $all_time['mday'] + ($inc_tomorrow ? 1 : 0), $all_time['year']); - - // Start with day - $ret = ""; - - // Hours - $ret .= " "; - - // Minutes - $ret .= " "; - - return $ret; -} - -if(! defined("USER_WIDTH")) -{ - define("USER_WIDTH", "width:97%"); -} - -//==================================================================== -// CONFIGURATION OPTIONS MENU -//==================================================================== - -/* -if($action == "config") -{ - // User Audit log options (for info) - //======================= - // define('USER_AUDIT_SIGNUP',11); // User signed up - // define('USER_AUDIT_EMAILACK',12); // User responded to registration email - // define('USER_AUDIT_LOGIN',13); // User logged in - // define('USER_AUDIT_LOGOUT',14); // User logged out - // define('USER_AUDIT_NEW_DN',15); // User changed display name - // define('USER_AUDIT_NEW_PW',16); // User changed password - // define('USER_AUDIT_NEW_EML',17); // User changed email - // define('USER_AUDIT_NEW_SET',19); // User changed other settings (intentional gap in numbering) - // define('USER_AUDIT_ADD_ADMIN', 20); // User added by admin - // define('USER_AUDIT_MAIL_BOUNCE', 21); // User mail bounce - // define('USER_AUDIT_BANNED', 22); // User banned - // define('USER_AUDIT_BOUNCE_RESET', 23); // User bounce reset - // define('USER_AUDIT_TEMP_ACCOUNT', 24); // User temporary account - - - $audit_checkboxes = array(USER_AUDIT_SIGNUP => RL_LAN_071, USER_AUDIT_EMAILACK => RL_LAN_072, USER_AUDIT_LOGIN => RL_LAN_073, // USER_AUDIT_LOGOUT => RL_LAN_074, // Logout is lumped in with login - USER_AUDIT_NEW_DN => RL_LAN_075, USER_AUDIT_NEW_PW => RL_LAN_076, USER_AUDIT_PW_RES => RL_LAN_078, USER_AUDIT_NEW_EML => RL_LAN_077, USER_AUDIT_NEW_SET => RL_LAN_079, - USER_AUDIT_ADD_ADMIN => RL_LAN_080, USER_AUDIT_MAIL_BOUNCE => RL_LAN_081, USER_AUDIT_BANNED => RL_LAN_082, USER_AUDIT_BOUNCE_RESET => RL_LAN_083, - USER_AUDIT_TEMP_ACCOUNT => RL_LAN_084); - - if(! isset($e_userclass) && ! is_object($e_userclass)) - { - require_once (e_HANDLER."userclass_class.php"); - $e_userclass = new user_class(); - } - - $user_signup_opts = array_flip(explode(',', varset($pref['user_audit_opts'], ''))); - - // Common to all logs - $text = " -
- ".RL_LAN_121." -
-
- ".RL_LAN_122." - - - - - - - - - - - "; - - // User Audit Trail Options - $text .= " - - - - - - - - - "; - - - // Rolling log options - //==================== - $text .= " - - - - - - - - - -
".RL_LAN_044."".$frm->select('sys_log_perpage', array(10, 20, 30, 40, 50), $pref['sys_log_perpage'])."".RL_LAN_064."
".RL_LAN_123." - - ".RL_LAN_026." -
".RL_LAN_031.""; - - foreach($audit_checkboxes as $k => $t) - { - $checked = isset($user_signup_opts[$k]) ? true : false; - $text .= $frm->checkbox('user_audit_opts[]',$k, $checked, array('label'=>$t)); - } - - - $text .= $frm->admin_button('check_all', 'jstarget:user_audit_opts', 'checkall', LAN_CHECKALL).$frm->admin_button('uncheck_all', 'jstarget:user_audit_opts', 'checkall', LAN_UNCHECKALL)." -
".RL_LAN_008." -
- ".$frm->checkbox('roll_log_active', 1, varset($pref['roll_log_active'],0))." -
-
".RL_LAN_009."".$frm->text('roll_log_days', $pref['roll_log_days'], 5)."
-
- ".$frm->admin_button('setoptions', 'no-value', 'update', LAN_UPDATE)." -
-
-
- "; - - // Admin log maintenance - //================== - $text .= " -
-
- ".RL_LAN_125." - - - - - - - - - - - "; - - // User log maintenance - //==================== - $text .= " - - - - - -
".RL_LAN_045." ".gen_log_delete('rolllog_clearadmin')." ".RL_LAN_046.$frm->admin_button('deleteoldadmin', 'no-value', 'delete', RL_LAN_049)."
".RL_LAN_066." ".gen_log_delete('rolllog_clearaudit')." ".RL_LAN_046.$frm->admin_button('deleteoldaudit', 'no-value', 'delete', RL_LAN_049)."
-
-
- -
- "; - - $ns->tablerender(ADLAN_155.SEP.LAN_OPTIONS, $mes->render().$text); -} -*/ - -//==================================================================== -// LOG VIEW MENU -//==================================================================== -if(isset($page_title[$action])) -{ - $from = intval(varset($qs[1], 0)); // First entry to display - $amount = max(varset($pref['sys_log_perpage'], 20), 5); // Number of entries per page - - - // Array decides which filters are active for each log. There are 4 columns total. All but 'datetimes' occupy 2. Must specify multiple of 4 columns - add 'blank' if necessary - $active_filters = array( - 'adminlog' => array('datetimes' => 0, 'ipfilter' => 0, 'userfilter' => 0, 'eventfilter' => 0, 'priority' => 0), - 'auditlog' => array('datetimes' => 0, 'ipfilter' => 0, 'userfilter' => 0, 'eventfilter' => 0, 'blank' => 2), - 'rolllog' => array('datetimes' => 0, 'ipfilter' => 0, 'userfilter' => 0, 'eventfilter' => 0, 'priority' => 0, 'callerfilter' => 0, 'blank' => 2), - 'downlog' => array('datetimes' => 0, 'ipfilter' => 0, 'userfilter' => 0, 'downloadidfilter' => 0, 'blank' => 2), - 'detailed' => array('datestart' => 0, 'ipfilter' => 0, 'userfilter' => 0, 'eventfilter' => 0, 'blank' => 2), - 'online' => array('ipfilter' => 0, 'userfilter' => 0)); - - // Arrays determine column widths, headings, displayed fields for each log - $col_fields = array( - 'adminlog' => array('cf_datestring', 'dblog_type', 'dblog_ip', 'dblog_user_id', 'user_name', 'dblog_eventcode', 'dblog_title', 'dblog_remarks'), - 'auditlog' => array('cf_datestring', 'dblog_ip', 'dblog_user_id', 'dblog_user_name', 'dblog_eventcode', 'dblog_title', 'dblog_remarks'), - 'rolllog' => array('cf_datestring', 'dblog_type', 'dblog_ip', 'dblog_user_id', 'dblog_user_name', 'dblog_eventcode', 'dblog_caller', 'dblog_title', 'dblog_remarks'), - 'downlog' => array('cf_datestring', 'dblog_ip', 'dblog_user_id', 'user_name', 'download_request_download_id', 'download_name'), - 'detailed' => array('cf_microtime', 'cf_microtimediff', 'source', 'dblog_type', 'dblog_ip', 'dblog_user_id', 'user_name', 'dblog_eventcode', 'dblog_title', 'dblog_remarks'), - 'online' => array('cf_datestring', 'dblog_ip', 'dblog_user_id', 'user_name', 'online_location', 'online_pagecount', 'online_flag', 'online_active')); - $col_widths = array( - 'adminlog' => array(18, 4, 14, 7, 15, 8, 14, 20), // Date - Pri - IP - UID - User - Code - Event - Info - 'auditlog' => array(18, 14, 7, 15, 8, 14, 24), - 'rolllog' => array(15, 4, 12, 6, 12, 7, 13, 13, 18), // Date - Pri - IP - UID - User - Code - Caller - Event - Info - 'downlog' => array(18, 14, 7, 15, 8, 38), - 'detailed' => array(10, 8, 6, 4, 14, 6, 17, 7, 17, 21), - 'comments' => array(14, 7, 7, 7, 14, 3, 10, 12, 5, 17, 1, 1, 1), - 'online' => array(18, 15, 7, 14, 32, 6, 4, 4)); - $col_titles = array( - 'adminlog' => array(RL_LAN_019, RL_LAN_032, RL_LAN_020, RL_LAN_104, LAN_USER, RL_LAN_023, LAN_TITLE, RL_LAN_033), - 'auditlog' => array(RL_LAN_019, RL_LAN_020, RL_LAN_104, LAN_USER, RL_LAN_023, LAN_TITLE, RL_LAN_033), - 'rolllog' => array(RL_LAN_019, RL_LAN_032, RL_LAN_020, RL_LAN_104, LAN_USER, RL_LAN_023, RL_LAN_024, LAN_TITLE, RL_LAN_033), - 'downlog' => array(RL_LAN_019, RL_LAN_020, RL_LAN_104, LAN_USER, RL_LAN_068, RL_LAN_069), - 'detailed' => array(LAN_TIME, RL_LAN_096, LAN_SOURCE, RL_LAN_032, RL_LAN_020, RL_LAN_104, LAN_USER, RL_LAN_023, LAN_TITLE, RL_LAN_033), - 'online' => array(RL_LAN_019, RL_LAN_020, LAN_ID, LAN_USER, RL_LAN_116, RL_LAN_117, RL_LAN_118, RL_LAN_116)); - - - - // Only need to define entries in this array if the base DB query is non-standard (i.e. different field names and/or joins) - $base_query = array('downlog' => "SELECT SQL_CALC_FOUND_ROWS - dbl.download_request_id as dblog_id, - dbl.download_request_userid as dblog_user_id, - dbl.download_request_ip as dblog_ip, - dbl.download_request_download_id, - dbl.download_request_datestamp as dblog_datestamp, - d.download_name, - u.user_name - FROM #download_requests AS dbl - LEFT JOIN #user AS u ON dbl.download_request_userid=u.user_id - LEFT JOIN #download AS d ON dbl.download_request_download_id=d.download_id - ", 'detailed' => "SELECT SQL_CALC_FOUND_ROWS cl.*, u.* FROM ( - SELECT dblog_datestamp + (dblog_microtime/1000000) AS dblog_time, dblog_user_id, dblog_eventcode, dblog_title, dblog_remarks, dblog_type, dblog_ip, 'roll' AS source FROM `#dblog` - UNION - SELECT dblog_datestamp + (dblog_microtime/1000000) AS dblog_time, dblog_user_id, dblog_eventcode, dblog_title, dblog_remarks, '-' AS dblog_type, dblog_ip, 'audit' AS source FROM `#audit_log` - UNION - SELECT dblog_datestamp + (dblog_microtime/1000000) AS dblog_time, dblog_user_id, dblog_eventcode, dblog_title, dblog_remarks, dblog_type, dblog_ip, 'admin' AS source FROM `#admin_log`) AS cl - LEFT JOIN `#user` AS u ON cl.dblog_user_id=u.user_id ", 'comments' => "SELECT SQL_CALC_FOUND_ROWS *, comment_datestamp AS dblog_datestamp FROM `#comments` AS c", 'online' => "SELECT SQL_CALC_FOUND_ROWS online_timestamp AS dblog_datestamp, - online_ip AS dblog_ip, - SUBSTRING_INDEX(online_user_id,'.',1) AS dblog_user_id, - SUBSTRING(online_user_id FROM LOCATE('.',online_user_id)+1) AS user_name, - `online_location`, `online_pagecount`, `online_flag`, `online_active` - FROM `#online`"); - - // The filters have to use the 'actual' db field names. So the following table sets the defaults and the exceptions which vary across the range of tables supported - $map_filters = array('default' => array('datetimes' => '`dblog_datestamp`', 'ipfilter' => '`dblog_ip`', 'userfilter' => '`dblog_user_id`', 'eventfilter' => '`dblog_eventcode`'), 'downlog' => array('datetimes' => '`download_request_datestamp`', 'ipfilter' => '`download_request_ip`', 'userfilter' => '`download_request_userid`'), 'detailed' => array('datestart' => '`dblog_time`'), 'comments' => array('datetimes' => '`comment_datestamp`', 'ipfilter' => '`comment_ip`', 'eventfilter' => 'comment_type', 'userfilter' => '`comment_author_id`'), 'online' => array('online_ip' => '`dblog_ip`', 'online_user_id' => '`dblog_user_id`')); - - // Field to sort table on - $sort_fields = array('default' => 'dblog_id', 'detailed' => 'dblog_time', 'comments' => 'comment_datestamp', 'online' => 'online_timestamp'); - - // Check things - if($start_time >= $end_time) - { // Make end time beginning of tomorrow - $tempdate = getdate(); - $end_time = mktime(0, 0, 0, $tempdate['mon'], $tempdate['mday'] + 1, $tempdate['year']); // Seems odd, but mktime will work this out OK - // (or so the manual says) - } - - // Now work out the query - only use those filters which are displayed - $qry = ''; - $and_array = array(); - foreach($active_filters[$action] as $fname => $fpars) - { - $filter_field = varset($map_filters[$action][$fname], $map_filters['default'][$fname]); - switch($fname) - { - case 'datetimes': - if($start_enabled && ($start_time > 0)) - $and_array[] = "{$filter_field} >= ".intval($start_time); - if($end_enabled && ($end_time > 0)) - $and_array[] = "{$filter_field} <= ".intval($end_time); - break; - case 'datestart': - if($start_time == 0) - { - $end_time = time(); - $start_time = $end_time - 300; // Default to last 5 mins - } - $and_array[] = "{$filter_field} >= ".intval($start_time); - $and_array[] = "{$filter_field} <= ".intval($end_time); - break; - case 'ipfilter': - if($ipaddress_filter != "") - { - if(substr($ipaddress_filter, - 1) == '*') - { // Wildcard to handle - mySQL uses % - $and_array[] = "{$filter_field} LIKE '".substr($ipaddress_filter, 0, - 1)."%' "; - } - else - { - $and_array[] = "{$filter_field}= '".$ipaddress_filter."' "; - } - } - break; - case 'userfilter': - if($user_filter != '') - $and_array[] = "{$filter_field} = ".intval($user_filter); - break; - case 'eventfilter': - if($event_filter != '') - { - if(substr($event_filter, - 1) == '*') - { // Wildcard to handle - mySQL uses % - $and_array[] = " {$filter_field} LIKE '".substr($event_filter, 0, - 1)."%' "; - } - else - { - $and_array[] = "{$filter_field}= '".$event_filter."' "; - } - } - break; - case 'callerfilter': - if($caller_filter != '') - { - if(substr($caller_filter, - 1) == '*') - { // Wildcard to handle - mySQL uses % - $and_array[] = "dblog_caller LIKE '".substr($caller_filter, 0, - 1)."%' "; - } - else - { - $and_array[] = "dblog_caller= '".$caller_filter."' "; - } - } - break; - case 'priority': - if(($pri_filter_val != "") && ($pri_filter_cond != "") && ($pri_filter_cond != "xx")) - { - switch($pri_filter_cond) - { - case "lt": - $and_array[] = "dblog_type <= '{$pri_filter_val}' "; - break; - case "eq": - $and_array[] = "dblog_type = '{$pri_filter_val}' "; - break; - case "gt": - $and_array[] = "dblog_type >= '{$pri_filter_val}' "; - break; - } - } - break; - case 'downloadidfilter': - if($downloadid_filter != '') - $and_array[] = "download_request_download_id = ".intval($downloadid_filter); - break; - } - } - - if(count($and_array)) - $qry = " WHERE ".implode(' AND ', $and_array); - - $limit_clause = " LIMIT {$from}, {$amount} "; - $sort_field = varset($sort_fields[$action], $sort_fields['default']); - - if(isset($base_query[$action])) - { - $qry = $base_query[$action].$qry." ORDER BY {$sort_field} ".$sort_order; - } - else - { - $qry = "SELECT SQL_CALC_FOUND_ROWS dbl.*,u.user_name FROM #".$log_db_table[$action]." AS dbl LEFT JOIN #user AS u ON dbl.dblog_user_id=u.user_id".$qry." ORDER BY {$sort_field} ".$sort_order; - } - - $num_entry = 0; - if($sql->gen($qry.$limit_clause)) - { - $num_entry = $sql->total_results; - } - if($from > $num_entry) - { - $from = 0; // We may be on a later page - $limit_clause = " LIMIT {$from}, {$amount} "; - $sql->gen($qry.$limit_clause); // Re-run query with new value of $from - $num_entry = $sql->total_results; - } - - // Start by putting up the filter boxes - $text = " -
-
- ".RL_LAN_012." - - - - - - - - "; - $filter_cols = 0; - foreach($active_filters[$action] as $fname => $fpars) - { - if($filter_cols == 0) - $text .= ''; - switch($fname) - { - case 'datetimes': - $text .= " - - - - - "; - $filter_cols = 4; - break; - case 'datestart': - $text .= " - - - - "; - $filter_cols = 4; - break; - case 'priority': - $text .= " - - - "; - $filter_cols += 2; - break; - case 'ipfilter': - $text .= " - - - "; - $filter_cols += 2; - break; - case 'userfilter': - $text .= " - - - "; - $filter_cols += 2; - break; - case 'eventfilter': - $text .= " - - - "; - $filter_cols += 2; - break; - case 'callerfilter': - $text .= " - - - "; - $filter_cols += 2; - break; - case 'downloadidfilter': - $text .= " - - "; - $filter_cols += 2; - break; - case 'blank': // Any number of blank cells - $text .= str_repeat("", $fpars); - $filter_cols += $fpars; - break; - } - if($filter_cols >= 4) - { - $text .= ''; - $filter_cols = 0; - } - } - - // $text .= ""; - $text .= " -
".$frm->checkbox('start-enabled', 1, varset($pref['start-enabled'],0))."".time_box("starttime", $start_time, $back_day_count[$action], FALSE)."".$frm->checkbox('end-enabled', 1, varset($pref['end-enabled'],0))."".time_box("endtime", $end_time, $back_day_count[$action], TRUE)."".RL_LAN_013."".time_box("starttime", $start_time, $back_day_count[$action], FALSE, TRUE)."".RL_LAN_092." - ".RL_LAN_093." - ".RL_LAN_058."".$frm->select('roll_pri_cond', array('xx' => ' ', 'gt' => '>=', 'eq' => '==', 'lt' => '<='), $pri_filter_cond)." - - ".RL_LAN_060." - - ".RL_LAN_061." - ".RL_LAN_015." - - ".RL_LAN_016." - ".RL_LAN_029." - - ".RL_LAN_061." - ".RL_LAN_059." - - ".RL_LAN_061." - ".RL_LAN_090." - -  
Query = ".$qry.$limit_clause."
{$_COOKIE[$rl_cookiename]}
-
- ".$frm->admin_button('clearfilters', 'no-value', 'delete', RL_LAN_114)." - ".$frm->admin_button('updatefilters', 'no-value', 'update', RL_LAN_028)." -
-
-
- "; - - // Next bit is the actual log display - the arrays define column widths, titles, fields etc for each log - $column_count = count($col_widths[$action]); - $text .= " -
-
- {$page_title[$action]} - - - "; - - foreach($col_widths[$action] as $i) - { - $text .= " - - "; - } - - $text .= " - - - "; - - if($num_entry == 0) - { - $text .= " - - - - "; - } - else - { // Start with header - $text .= ' - - - '; - $count = 1; - foreach($col_titles[$action] as $ct) - { - count($col_titles[$action]); - $text .= " - {$ct} - "; - $count ++; - } - $text .= " - - - - "; - - // Routine to handle the simple bbcode-like codes for log body text - function log_process($matches) - { - switch($matches[1]) - { - case 'br': - return '
'; - case 'link': - $temp = substr($matches[2], 1); - return "{$temp}"; - case 'test': - return '----TEST----'; - default: - return $matches[0]; // No change - } - } - // Now put up the events - $delete_button = FALSE; - while($row = $sql->db_Fetch()) - { - $text .= ''; - foreach($col_fields[$action] as $cf) - { - switch($cf) - { - case 'cf_datestring': - $val = date(AL_DATE_TIME_FORMAT, $row['dblog_datestamp']); - break; - case 'cf_microtime': - $val = date("H:i:s", intval($row['dblog_time']) % 86400).'.'.str_pad(100000 * round($row['dblog_time'] - floor($row['dblog_time']), 6), 6, '0'); - break; - case 'cf_microtimediff': - $val = ' '; - if($last_noted_time > 0) - { - $val = number_format($last_noted_time - $row['dblog_time'], 6, '.', ''); - } - $last_noted_time = $row['dblog_time']; - break; - case 'cf_eventcode': - $val = 'ADMIN'.$row['dblog_eventcode']; - break; - case 'dblog_title': // Look up constants to give multi-language viewing - $val = trim($row['dblog_title']); - if(defined($val)) - $val = constant($val); - break; - case 'dblog_user_name': - $val = $row['dblog_user_id'] ? $row['dblog_user_name'] : LAN_ANONYMOUS; - break; - case 'user_name': - $val = $row['dblog_user_id'] ? $row['user_name'] : LAN_ANONYMOUS; - break; - case 'dblog_caller': - $val = $row['dblog_caller']; - if((strpos($val, '|') !== FALSE) && (strpos($val, '@') !== FALSE)) - { - list($file, $rest) = explode('|', $val); - list($routine, $rest) = explode('@', $rest); - $val = $file.'
Function: '.$routine.'
Line: '.$rest; - } - break; - case 'dblog_remarks': - // Look for pseudo-code for newlines, link insertion - $val = preg_replace_callback("#\[!(\w+?)(=.+?){0,1}!]#", 'log_process', $row['dblog_remarks']); - break; - case 'dblog_ip': - $val = e107::getIPHandler()->ipDecode($row['dblog_ip']); - break; - case 'comment_ip': - $val = e107::getIPHandler()->ipDecode($row['comment_ip']); - /* if (strlen($val) == 8) // New decoder should handle this automatically - { - $hexip = explode('.', chunk_split($val, 2, '.')); - $val = hexdec($hexip[0]). '.'.hexdec($hexip[1]).'.'.hexdec($hexip[2]).'.'.hexdec($hexip[3]); - } */ - break; - case 'comment_comment': - $val = $tp->text_truncate($row['comment_comment'], 100, '...'); // Just display first bit of comment - break; - case 'online_location': - $val = str_replace($e107->base_path, '', $row['online_location']); // Just display site-specific bit of path - break; - case 'del_check': // Put up a 'delete' checkbox - $val = ""; - $delete_button = TRUE; - break; - default: - $val = $row[$cf]; - } - $text .= ""; - } - $text .= ""; - } - } - $text .= " - -
".RL_LAN_017."
{$val}
-
- ".$frm->admin_button('refreshlog', 'no-value', 'submit', RL_LAN_018)." - "; - if($delete_button) - { - $text .= $frm->admin_button('deleteitems', 'no-value', 'delete', RL_LAN_11); - } - $text .= " -
-
-
- "; - - // Next-Previous. ========================== - - $text .= sprintf(str_replace("[x]", "%d", RL_LAN_126), $num_entry); - if($num_entry > $amount) - { - $parms = "{$num_entry},{$amount},{$from},".e_SELF."?".$action.".[FROM]"; - $text .= "
".$tp->parseTemplate("{NEXTPREV={$parms}}")."
"; - } - - $ns->tablerender("{$page_title[$action]}", $mes->render().$text); -} - -function admin_log_adminmenu() -{ - if(e_QUERY) - { - $tmp = explode(".", e_QUERY); - $action = $tmp[0]; - } - if($action == "") - { - $action = "adminlog"; - } - $var['adminlog']['text'] = RL_LAN_030; - $var['adminlog']['link'] = "admin_log.php?adminlog"; - - $var['auditlog']['text'] = RL_LAN_062; - $var['auditlog']['link'] = "admin_log.php?auditlog"; - - $var['rolllog']['text'] = RL_LAN_002; - $var['rolllog']['link'] = "admin_log.php?rolllog"; - - $var['downlog']['text'] = RL_LAN_067; - $var['downlog']['link'] = "admin_log.php?downlog"; - - $var['detailed']['text'] = RL_LAN_091; - $var['detailed']['link'] = "admin_log.php?detailed"; - -// Deprecated by Comments Manager. -/* - $var['comments']['text'] = 'Comments'; - $var['comments']['link'] = "admin_log.php?comments"; -*/ - $var['config']['text'] = LAN_OPTIONS; - $var['config']['link'] = "admin_log.php?config"; - - /* XXX - why?! - if($action == 'comments') - { - $var['users']['text'] = RL_LAN_115; - $var['users']['link'] = "users.php"; - } - */ - e107::getNav()->admin(RL_LAN_005, $action, $var); -} - -require_once (e_ADMIN."footer.php"); - - - -/** - * Handle page DOM within the page header - * - * @return string JS source - *//* -function headerjs() -{ - require_once(e_HANDLER.'js_helper.php'); - $ret = " - - - "; - - return $ret; -}*/ - -?> + $file) + { + $file = str_replace('--LAN--', e_LANGUAGE, $file); + + // echo "orig = ".$file." "; + //e107::lan($path,'log',true); + e107::includeLan(e_PLUGIN.$path.'/languages/'.$file); + } +} + +define('AL_DATE_TIME_FORMAT', 'y-m-d H:i:s'); + + + +class adminlog_admin extends e_admin_dispatcher +{ + + protected $modes = array( + + 'main' => array( + 'controller' => 'admin_log_ui', + 'path' => null, + 'ui' => 'admin_log_form_ui', + 'uipath' => null + ), + + + 'audit' => array( + 'controller' => 'audit_log_ui', + 'path' => null, + 'ui' => 'admin_log_form_ui', + 'uipath' => null + ), + + + 'rolling' => array( + 'controller' => 'dblog_ui', + 'path' => null, + 'ui' => 'admin_log_form_ui', + 'uipath' => null + ), + + + ); + + //$page_title = array('adminlog' => RL_LAN_030, 'auditlog' => RL_LAN_062, 'rolllog' => RL_LAN_002, 'downlog' => RL_LAN_067, 'detailed' => RL_LAN_094, 'online' => RL_LAN_120); + + + protected $adminMenu = array( + + 'main/list' => array('caption'=> RL_LAN_030, 'perm' => '5'), + 'audit/list' => array('caption'=> RL_LAN_062, 'perm' => '5'), + 'rolling/list' => array('caption'=> RL_LAN_002, 'perm' => '5'), + 'divider/01' => array('divider'=>true), + 'main/prefs' => array('caption'=> LAN_PREFS, 'perm' => '5'), + 'main/maintenance' => array('caption'=> LAN_OPTIONS, 'perm' => '5') + + // 'main/custom' => array('caption'=> 'Custom Page', 'perm' => 'P') + ); + + protected $adminMenuAliases = array( + 'main/edit' => 'main/list' + ); + + protected $adminMenuIcon = 'e-adminlogs-24'; + + protected $menuTitle = ADLAN_155; + + function init() + { + + e107::css('inline', " + + .fa { font-size:130% } + .fa-question-circle { } + .fa-exclamation-circle { color: #FAA732 } + .fa-warning { color: red } + + + + "); + + + } +} + + + + + +class admin_log_ui extends e_admin_ui +{ + + protected $pluginTitle = ADLAN_155; + protected $pluginName = 'core'; + protected $table = 'admin_log'; + protected $pid = 'dblog_id'; + protected $perPage = 10; + // protected $listQry = "SELECT f.*, u.* FROM #admin_log AS f LEFT JOIN #user AS u ON f.dblog_user_id = u.user_id "; // Should not be necessary. + + protected $listQry = "SELECT SQL_CALC_FOUND_ROWS f.*, u.user_id, u.user_name FROM #admin_log AS f LEFT JOIN #user AS u ON f.dblog_user_id = u.user_id "; // Should not be required but be auto-calculated. + protected $listOrder = 'f.dblog_id DESC'; + + protected $batchDelete = false; + protected $batchDeleteLog = false; //TODO - AdminUI option to disable logging of changes. + + protected $fields = array ( + // 'checkboxes' => array ( 'title' => '', 'type' => null, 'data' => null, 'nolist'=>true, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect', ), + 'dblog_id' => array ( 'title' => LAN_ID, 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_datestamp' => array ( 'title' => LAN_DATESTAMP, 'type' => 'datestamp', 'data' => 'int', 'width' => '12%', 'filter' => true, 'help' => '', 'readParms' => array('mask'=>'dd MM yyyy hh:ii:ss'), 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + // 'dblog_microtime' => array ( 'title' => 'Microtime', 'type' => 'method', 'data' => 'int', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), + 'dblog_type' => array ( 'title' => RL_LAN_032, 'type' => 'method', 'data' => 'int', 'width' => '5%', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), + 'dblog_ip' => array ( 'title' => LAN_IP, 'type' => 'ip', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + + 'dblog_user_id' => array ( 'title' => LAN_USER, 'type' => 'user', 'data' => 'int', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms'=>'link=1', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_eventcode' => array ( 'title' => RL_LAN_023, 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + + 'dblog_title' => array ( 'title' => LAN_TITLE, 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_remarks' => array ( 'title' => RL_LAN_033, 'type' => 'method', 'data' => 'str', 'width' => '35%', 'filter'=>true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'options' => array ( 'title' => LAN_OPTIONS, 'type' => null, 'nolist'=>true, 'data' => null, 'width' => '10%', 'thclass' => 'center last', 'class' => 'center last', 'forced' => '1', ), + ); + + protected $fieldpref = array( 'dblog_datestamp', 'dblog_type', 'dblog_eventcode', 'dblog_user_id', 'dblog_ip', 'dblog_title', 'dblog_remarks'); + + //'adminlog' => array(RL_LAN_019, RL_LAN_032, RL_LAN_020, RL_LAN_104, LAN_USER, RL_LAN_023, LAN_TITLE, RL_LAN_033), + + + protected $prefs = array( + 'sys_log_perpage' => array('title'=> RL_LAN_044, 'type'=>'dropdown', 'data' => 'int','help'=> RL_LAN_064,'writeParms'=>''), + 'user_audit_class' => array('title'=> RL_LAN_123, 'type'=>'userclass', 'data' => 'int','help'=>''), + 'user_audit_opts' => array('title'=> RL_LAN_031, 'type'=>'method', 'data' => 'array','help'=>''), + 'roll_log_active' => array('title'=> RL_LAN_008, 'type'=>'boolean', 'data' => 'int','help'=>''), + 'roll_log_days' => array('title'=> RL_LAN_009, 'type'=>'number', 'data' => 'string','help'=>''), + // 'Delete admin log events older than ' => array('title'=> RL_LAN_045, 'type'=>'method', 'data' => 'string','help'=>'Help Text goes here'), + // 'Delete user audit trail log events older' => array('title'=> 'Delete user audit trail log events older', 'type'=>'method', 'data' => 'string','help'=>'Help Text goes here'), + ); + + + + + + + + + + + + + + + + + public $eventTypes = array(); + + // optional + public function init() + { + $perPage = e107::getConfig()->get('sys_log_perpage'); + $this->perPage = vartrue($perPage,10); + + $this->prefs['sys_log_perpage']['writeParms'] = array(10=>10, 15=>15, 20=>20, 30=>30, 40=>40, 50=>50); + + + $sql = e107::getDb(); + $row = $sql->retrieve("SELECT dblog_eventcode,dblog_title FROM #admin_log WHERE dblog_eventcode !='' AND dblog_title !='' GROUP BY dblog_eventcode",true); + foreach($row as $val) + { + $id = $val['dblog_eventcode']; + $def = strpos($val['dblog_title'], "LAN") !== false ? $id : $val['dblog_title']; + $this->eventTypes[$id] = str_replace(': [x]', '', deftrue($val['dblog_title'],$def)); + } + + asort($this->eventTypes); + + if(getperms('0')) + { + + $arr = array_reverse($this->fields, true); + $arr['checkboxes'] = array ( 'title' => '', 'type' => null, 'data' => null, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect' ); + + $this->fields = array_reverse($arr, true); + $this->batchDelete = true; + } + } + + + function gen_log_delete($selectname) + { + $values = array(360, 180, 90, 60, 30, 21, 20, 14, 10, 7, 6, 5, 4, 3, 2, 1); + return e107::getForm()->select($selectname, $values, '', 'useValues=1&size=small'); + } + + + function maintenancePage() + { + + if(!empty($_POST['deleteoldadmin']) || !empty($_POST['deleteoldaudit'])) + { + $this->maintenanceProcess(); + + } + + $frm = e107::getForm(); + + + + // Admin log maintenance + //================== + $text = " +
+
+ ".RL_LAN_125." + + + + + + + + + + + "; + + // User log maintenance + //==================== + $text .= " + + + + + +
".RL_LAN_045." ".$this->gen_log_delete('rolllog_clearadmin')." ".RL_LAN_046." ".$frm->admin_button('deleteoldadmin', 'no-value', 'delete', RL_LAN_049)."
".RL_LAN_066." ".$this->gen_log_delete('rolllog_clearaudit')." ".RL_LAN_046." ".$frm->admin_button('deleteoldaudit', 'no-value', 'delete', RL_LAN_049)."
+
+
+ + + "; + return $text; + + } + + + function maintenanceProcess() + { + $mes = e107::getMessage(); + $ns = e107::getRender(); + $log = e107::getAdminLog(); + $frm = e107::getForm(); + $sql = e107::getDb(); + + // print_a($_POST); + + if(!empty($_POST['deleteoldadmin']) && isset($_POST['rolllog_clearadmin'])) + { + $back_count = intval($_POST['rolllog_clearadmin']); + $_POST['backdeltype'] = 'confdel'; + $action = 'backdel'; + } + elseif(!empty($_POST['deleteoldaudit']) && isset($_POST['rolllog_clearaudit'])) + { + $back_count = intval($_POST['rolllog_clearaudit']); + $action = 'backdel'; + $_POST['backdeltype'] = 'auditdel'; + } + + /* + if(isset($back_count)) + { + if(($back_count >= 1) && ($back_count <= 90)) + { + $temp_date = getdate(); + $old_date = intval(mktime(0, 0, 0, $temp_date['mon'], $temp_date['mday'] - $back_count, $temp_date['year'])); + $old_string = strftime("%d %B %Y", $old_date); + // $message = "Back delete ".$back_count." days. Oldest date = ".$old_string; + $action = $next_action; + $qs[1] = $old_date; + $qs[2] = $back_count; + } + else + { + $mes->addWarning(RL_LAN_050); + } + } + */ + + $old_date = strtotime($back_count.' days ago'); + + + // Actually delete back events - admin or user audit log + if(($action == "backdel") && isset($_POST['backdeltype'])) + { + // $old_date = intval($qs[1]); + $old_string = strftime("%d %B %Y", $old_date); + $qry = "dblog_datestamp < ".$old_date; // Same field for both logs + + switch($_POST['backdeltype']) + { + case 'confdel': + $db_table = 'admin_log'; + $db_name = RL_LAN_052; + $db_msg = "ADLOG_02"; + break; + case 'auditdel': + $db_table = 'audit_log'; + $db_name = RL_LAN_053; + $db_msg = "ADLOG_03"; + break; + default: + exit(); // Someone fooling around! + } + + + e107::getMessage()->addDebug("Back delete,
oldest date = {$old_string}
Query = {$qry}"); + + if($del_count = $sql->delete($db_table, $qry)) + { + // Add in a log event + $message = $db_name.str_replace(array('[x]', '[y]'), array($old_string, $del_count), RL_LAN_057); + $mes->addSuccess($message); + $log->log_event($db_msg, "db_Delete - earlier than {$old_string} (past {$back_count} days)[!br!]".$message.'[!br!]'.$db_table.' '.$qry, E_LOG_INFORMATIVE, ''); + } + else + { + $mes->addWarning(RL_LAN_054." : ".$sql->mySQLresult); + } + + } + + // Prompt to delete back events + /* + if(($action == "confdel") || ($action == "auditdel")) + { + $old_string = strftime("%d %B %Y", $qs[1]); + $text = " +
+
+ ".LAN_CONFDELETE." + + + + +
+ ".(($action == "confdel") ? RL_LAN_047 : RL_LAN_065).$old_string." +
+
+ + ".$frm->admin_button('confirmdeleteold', 'no-value', 'delete', RL_LAN_049)." + ".$frm->admin_button('confirmcancelold', 'no-value', 'delete', LAN_CANCEL)." +
+
+
+ + "; + + $ns->tablerender(LAN_CONFDELETE, $text); + } + + */ + + } + + + +} + + +class admin_log_form_ui extends e_admin_form_ui +{ + + function sys_log_perpage($curVal,$mode) + { + $frm = e107::getForm(); + switch($mode) + { + case 'write': // Edit Page + return $frm->text('sys_log_perpage',$curVal); + break; + } + } + + function user_audit_opts($curVal,$mode) + { + + $frm = e107::getForm(); + + // User Audit log options (for info) + //======================= + // define('USER_AUDIT_SIGNUP',11); // User signed up + // define('USER_AUDIT_EMAILACK',12); // User responded to registration email + // define('USER_AUDIT_LOGIN',13); // User logged in + // define('USER_AUDIT_LOGOUT',14); // User logged out + // define('USER_AUDIT_NEW_DN',15); // User changed display name + // define('USER_AUDIT_NEW_PW',16); // User changed password + // define('USER_AUDIT_NEW_EML',17); // User changed email + // define('USER_AUDIT_NEW_SET',19); // User changed other settings (intentional gap in numbering) + // define('USER_AUDIT_ADD_ADMIN', 20); // User added by admin + // define('USER_AUDIT_MAIL_BOUNCE', 21); // User mail bounce + // define('USER_AUDIT_BANNED', 22); // User banned + // define('USER_AUDIT_BOUNCE_RESET', 23); // User bounce reset + // define('USER_AUDIT_TEMP_ACCOUNT', 24); // User temporary account + + + $audit_checkboxes = array(USER_AUDIT_SIGNUP => RL_LAN_071, USER_AUDIT_EMAILACK => RL_LAN_072, + USER_AUDIT_LOGIN => LAN_AUDIT_LOG_013, USER_AUDIT_LOGOUT => LAN_AUDIT_LOG_014, // Logout is lumped in with login + USER_AUDIT_NEW_DN => RL_LAN_075, USER_AUDIT_NEW_PW => RL_LAN_076, USER_AUDIT_PW_RES => RL_LAN_078, USER_AUDIT_NEW_EML => RL_LAN_077, USER_AUDIT_NEW_SET => RL_LAN_079, + USER_AUDIT_ADD_ADMIN => RL_LAN_080, USER_AUDIT_MAIL_BOUNCE => RL_LAN_081, USER_AUDIT_BANNED => RL_LAN_082, USER_AUDIT_BOUNCE_RESET => RL_LAN_083, + USER_AUDIT_TEMP_ACCOUNT => RL_LAN_084); + + $userAuditOpts = e107::getConfig()->get('user_audit_opts'); + + $text = ""; + + foreach($audit_checkboxes as $k => $t) + { + $checked = isset($userAuditOpts[$k]) ? true : false; + $text .= $frm->checkbox('user_audit_opts['.$k.']',$k, $checked, array('label'=>$t)); + } + + $text .= $frm->admin_button('check_all', 'jstarget:user_audit_opts', 'checkall', LAN_CHECKALL).$frm->admin_button('uncheck_all', 'jstarget:user_audit_opts', 'checkall', LAN_UNCHECKALL); + + + return $text; + } + + + + + // Custom Method/Function + /* + function dblog_datestamp($curVal,$mode) + { + $frm = e107::getForm(); + + switch($mode) + { + case 'read': // List Page + return date(AL_DATE_TIME_FORMAT, $curVal); + break; + + case 'write': // Edit Page + return $frm->text('dblog_datestamp',$curVal); + break; + + case 'filter': + case 'batch': + return $array; + break; + } + } + */ + + // Custom Method/Function + function dblog_microtime($curVal,$mode) + { + $frm = e107::getForm(); + + switch($mode) + { + case 'read': // List Page + return date("H:i:s", intval($curVal) % 86400).'.'.str_pad(100000 * round($curVal - floor($curVal), 6), 6, '0'); + break; + + case 'write': // Edit Page + return $frm->text('dblog_microtime',$curVal); + break; + + case 'filter': + case 'batch': + return $array; + break; + } + } + + + // Custom Method/Function + function dblog_type($curVal,$mode) + { + $tp = e107::getParser(); + /* + define("E_LOG_INFORMATIVE", 0); // Minimal Log Level, including really minor stuff + define("E_LOG_NOTICE", 1); // More important than informative, but less important than notice + define("E_LOG_WARNING", 2); // Not anything serious, but important information + define("E_LOG_FATAL", 3); // An event so bad your site ceased execution. + define("E_LOG_PLUGIN", 4); // Plugin information + */ + + $array = array( + ' ', // Minimal Log Level, including really minor stuff + '', //FIXME - should be the blue icon. // More important than informative, but less important than notice + '', // Not anything serious, but important information + '', // An event so bad your site ceased execution. + ' ' // Plugin information - Deprecated - Leave empty. + ); + + $array[1] = $tp->toGlyph('fa-question-circle'); + $array[2] = $tp->toGlyph('fa-exclamation-circle'); + $array[3] = $tp->toGlyph('fa-warning'); + + switch($mode) + { + case 'read': // List Page + return varset($array[$curVal], $curVal); + break; + + case 'filter': + case 'batch': + return array(RL_LAN_132,RL_LAN_133,RL_LAN_134,RL_LAN_135); + break; + } + } + + + + // Custom Method/Function + function dblog_title($curVal,$mode) + { + $tp = e107::getParser(); + + switch($mode) + { + case 'read': // List Page + + + + $val = trim($curVal); + if(defined($val)) + { + $val = constant($val); + } + + if(strpos($val,'[x]') !== false) + { + $remark = $this->getController()->getListModel()->get('dblog_remarks'); + preg_match("/\[table\]\s=>\s([\w]*)/i",$remark, $match); + + if(!empty($match[1])) + { + $val = $tp->lanVars($val, ''.$match[1].''); + } + else + { + preg_match("/\[!br!\]TABLE: ([\w]*)/i", $remark, $m); + if(!empty($m[1])) + { + $val = $tp->lanVars($val, ''.$m[1].''); + } + } + + + } + + return $val; + break; + + case 'filter': + case 'batch': + return null; + break; + } + } + + + function dblog_eventcode($curVal,$mode) + { + $array = $this->getController()->eventTypes; + + switch($mode) + { + case 'read': // List Page + return $curVal; + break; + + case 'filter': + case 'batch': + return $array; + break; + } + } + + + // Custom Method/Function + function dblog_remarks($curVal,$mode) + { + $frm = e107::getForm(); + $tp = e107::getParser(); + + switch($mode) + { + case 'read': // List Page + + $text = preg_replace_callback("#\[!(\w+?)(=.+?){0,1}!]#", 'log_process', $curVal); + $text = $tp->toHTML($text,false,'E_BODY'); + + if(strpos($text,'Array')!==false || strlen($text)>300) + { + $id = $this->getController()->getListModel()->get('dblog_id'); + $ret ="".RL_LAN_087.""; + $ret .= ""; + return $ret; + } + + return $text; + break; + + + case 'filter': + case 'batch': + return $array; + break; + } + } + +// Custom Method/Function + function dblog_caller($curVal,$mode) + { + + switch($mode) + { + case 'read': // List Page + $val =$curVal; + if((strpos($val, '|') !== FALSE) && (strpos($val, '@') !== FALSE)) + { + list($file, $rest) = explode('|', $val); + list($routine, $rest) = explode('@', $rest); + $val = $file.'
Function: '.$routine.'
Line: '.$rest; + } + return $val; + break; + + + case 'filter': + case 'batch': + return $array; + break; + } + } + +} + + + +class audit_log_ui extends e_admin_ui +{ + + protected $pluginTitle = ADLAN_155; + protected $pluginName = 'adminlog'; + protected $table = 'audit_log'; + protected $pid = 'dblog_id'; + protected $perPage = 10; + protected $listOrder = 'dblog_id DESC'; + protected $batchDelete = true; + + protected $fields = array ( + 'checkboxes' => array ( 'title' => '', 'type' => null, 'data' => null, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect', ), + 'dblog_id' => array ( 'title' => LAN_ID, 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_datestamp' => array ( 'title' => LAN_DATESTAMP, 'type' => 'datestamp', 'data' => 'int', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => array('mask'=>'dd MM yyyy hh:ii:ss'), 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_microtime' => array ( 'title' => 'Microtime', 'type' => 'text', 'data' => 'int', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), + 'dblog_eventcode' => array ( 'title' => 'Eventcode', 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), + 'dblog_user_id' => array ( 'title' => LAN_USER, 'type' => 'user', 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_user_name' => array ( 'title' => LAN_USER, 'type' => 'text', 'data' => 'str', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_ip' => array ( 'title' => LAN_IP, 'type' => 'ip', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_title' => array ( 'title' => LAN_TITLE, 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_remarks' => array ( 'title' => 'Remarks', 'type' => 'method', 'data' => 'str', 'width' => '30%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'options' => array ( 'title' => LAN_OPTIONS, 'type' => null, 'nolist'=>true, 'data' => null, 'width' => '10%', 'thclass' => 'center last', 'class' => 'center last', 'forced' => '1', ), + ); + + protected $fieldpref = array('dblog_id', 'dblog_datestamp', 'dblog_microtime', 'dblog_eventcode', 'dblog_user_id', 'dblog_user_name', 'dblog_ip', 'dblog_title','dblog_remarks'); + + + + // optional + public function init() + { + $perPage = e107::getConfig()->get('sys_log_perpage'); + $this->perPage = vartrue($perPage,10); + } + + /* + public function customPage() + { + $ns = e107::getRender(); + $text = 'Hello World!'; + $ns->tablerender('Hello',$text); + + } + */ + +} + + + + + + + +class dblog_ui extends e_admin_ui +{ + + protected $pluginTitle = ADLAN_155; + protected $pluginName = 'adminlog'; + protected $table = 'dblog'; + protected $pid = 'dblog_id'; + protected $perPage = 15; + protected $listOrder = 'dblog_id desc'; + + protected $fields = array ( + 'checkboxes' => array ( 'title' => '', 'type' => null, 'data' => null, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect', ), + // 'dblog_id' => array ( 'title' => LAN_ID, 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_datestamp' => array ( 'title' => LAN_DATESTAMP, 'type' => 'datestamp', 'data' => 'int', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => array('mask'=>'dd MM yyyy hh:ii:ss'), 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_microtime' => array ( 'title' => 'Microtime', 'type' => 'method', 'data' => 'int', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), + 'dblog_type' => array ( 'title' => LAN_TYPE, 'type' => 'method', 'data' => 'int', 'width' => 'auto', 'batch' => true, 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_eventcode' => array ( 'title' => 'Eventcode', 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), + 'dblog_user_id' => array ( 'title' => LAN_ID, 'type' => 'user', 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_user_name' => array ( 'title' => LAN_USER, 'type' => 'text', 'data' => 'str', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_ip' => array ( 'title' => LAN_IP, 'type' => 'ip', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_caller' => array ( 'title' => 'Caller', 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), + 'dblog_title' => array ( 'title' => LAN_TITLE, 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'dblog_remarks' => array ( 'title' => 'Remarks', 'type' => 'method', 'data' => 'str', 'width' => '30%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'options' => array ( 'title' => LAN_OPTIONS, 'type' => null, 'nolist'=>true, 'data' => null, 'width' => '10%', 'thclass' => 'center last', 'class' => 'center last', 'forced' => '1', ), + ); + + protected $fieldpref = array('dblog_id', 'dblog_datestamp', 'dblog_microtime', 'dblog_type', 'dblog_eventcode', 'dblog_user_id', 'dblog_user_name', 'dblog_ip', 'dblog_caller', 'dblog_title', 'dblog_remarks'); + + + // optional + public function init() + { + $perPage = e107::getConfig()->get('sys_log_perpage'); + $this->perPage = vartrue($perPage,10); + } + +} + + + + +// Routine to handle the simple bbcode-like codes for log body text + + function log_process($matches) + { + switch($matches[1]) + { + case 'br': + return '
'; + case 'link': + $temp = substr($matches[2], 1); + return "{$temp}"; + case 'test': + return '----TEST----'; + default: + return $matches[0]; // No change + } + } + + + + + + +new adminlog_admin(); + +require_once(e_ADMIN."auth.php"); +e107::getAdminUI()->runPage(); + +require_once(e_ADMIN."footer.php"); +exit; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Everything below this point is currently unused, but left for reference in case of bugs. +// ---------------------------------------------------------------------------------------------------------- + + + + + + + + +if(is_array($pref['lan_log_list'])) //... and for any plugins which support it +{ + foreach($pref['lan_log_list'] as $path => $file) + { + $file = str_replace('--LAN--', e_LANGUAGE, $file); + + // echo "orig = ".$file." "; + //e107::lan($path,'log',true); + e107::includeLan(e_PLUGIN.$path.'/languages/'.$file); + } +} + +unset($qs); + +require_once (e_ADMIN.'auth.php'); + +$mes = e107::getMessage(); +$frm = e107::getForm(); + +define('AL_DATE_TIME_FORMAT', 'y-m-d H:i:s'); +/* +if(isset($_POST['setoptions'])) +{ + unset($temp); + + if(in_array((string) USER_AUDIT_LOGIN, $_POST['user_audit_opts'])) + { + $_POST['user_audit_opts'][] = USER_AUDIT_LOGOUT; + } + foreach($_POST['user_audit_opts'] as $k => $v) + { + if(! is_numeric($v)) + { + unset($_POST['user_audit_opts'][$k]); + } + } + $temp['roll_log_active'] = intval($_POST['roll_log_active']); + $temp['roll_log_days'] = intval($_POST['roll_log_days']); + $temp['sys_log_perpage'] = intval($_POST['sys_log_perpage']); + $temp['user_audit_opts'] = implode(',', $_POST['user_audit_opts']); + $temp['user_audit_class'] = intval($_POST['user_audit_class']); + + if($admin_log->logArrayDiffs($temp, $pref, 'ADLOG_01') || $admin_log->logArrayDiffs($temp, $pref, 'ADLOG_04')) + { + save_prefs(); // Only save if changes + } + else + { + $mes->addInfo(LAN_NO_CHANGE); + } + +} +*/ + +$ns->tablerender($caption, $mes->render() . $text); + +if(e_QUERY) +{ // Must explode after calling auth.php + $qs = explode(".", e_QUERY); +} + +$action = varset($qs[0], 'adminlog'); + +// Deprecated by Comments Manager +/* +if(isset($_POST['deleteitems']) && ($action == 'comments')) +{ + $c_list = array(); + foreach($_POST['del_item'] as $di) + { + if(intval($di) > 0) + $c_list[] = '`comment_id`='.intval($di); + } + if($count = $sql->db_Delete('comments', implode(' OR ', $c_list))) + { + //$text = str_replace('--NUMBER--', $count,RL_LAN_112); + $emessage->add(str_replace('--NUMBER--', $count, RL_LAN_112), E_MESSAGE_SUCCESS); + e107::getLog()->add('COMMENT_01', 'ID: '.implode(',', $_POST['del_item']), E_LOG_INFORMATIVE, ''); + } + else + { + //$text = RL_LAN_113; + $emessage->add(RL_LAN_113, E_MESSAGE_WARNING); + } + //$ns -> tablerender(LAN_DELETE, "
".$text."
"); + unset($c_list); +} +*/ + +// ****************** MAINTENANCE ****************** +unset($back_count); +if(isset($_POST['deleteoldadmin']) && isset($_POST['rolllog_clearadmin'])) +{ + $back_count = intval($_POST['rolllog_clearadmin']); + $next_action = 'confdel'; +} +elseif(isset($_POST['deleteoldaudit']) && isset($_POST['rolllog_clearaudit'])) +{ + $back_count = intval($_POST['rolllog_clearaudit']); + $next_action = 'auditdel'; +} + +if(isset($back_count) && isset($next_action)) +{ + if(($back_count >= 1) && ($back_count <= 90)) + { + $temp_date = getdate(); + $old_date = intval(mktime(0, 0, 0, $temp_date['mon'], $temp_date['mday'] - $back_count, $temp_date['year'])); + $old_string = strftime("%d %B %Y", $old_date); + // $message = "Back delete ".$back_count." days. Oldest date = ".$old_string; + $action = $next_action; + $qs[1] = $old_date; + $qs[2] = $back_count; + } + else + { + $mes->addWarning(RL_LAN_050); + } +} + +if(!isset($admin_log)) +{ + $mes->addWarning("Admin Log not valid"); +} + + +// Actually delete back events - admin or user audit log +if(($action == "backdel") && isset($_POST['backdeltype'])) +{ + if(isset($_POST['confirmdeleteold'])) + { + $old_date = intval($qs[1]); + $old_string = strftime("%d %B %Y", $old_date); + $qry = "dblog_datestamp < ".$old_date; // Same field for both logs + switch($_POST['backdeltype']) + { + case 'confdel': + $db_table = 'admin_log'; + $db_name = RL_LAN_052; + $db_msg = "ADLOG_02"; + break; + case 'auditdel': + $db_table = 'audit_log'; + $db_name = RL_LAN_053; + $db_msg = "ADLOG_03"; + break; + default: + exit(); // Someone fooling around! + } + // $message = "Back delete, oldest date = {$old_string} Query = {$qry}"; + if($del_count = $sql->db_Delete($db_table, $qry)) + { + // Add in a log event + $message = $db_name.str_replace(array('[x]', '[y]'), array($old_string, $del_count), RL_LAN_057); + $mes->addSuccess($message); + e107::getLog()->add($db_msg, "db_Delete - earlier than {$old_string} (past {$qs[2]} days)[!br!]".$message.'[!br!]'.$db_table.' '.$qry, E_LOG_INFORMATIVE, ''); + } + else + { + $mes->addWarning(RL_LAN_054." : ".$sql->mySQLresult); + } + } + else + { + $mes->addInfo(LAN_NO_CHANGE); + } + + $action = "config"; + unset($qs[1]); + unset($qs[2]); +} + +// Prompt to delete back events +if(($action == "confdel") || ($action == "auditdel")) +{ + $old_string = strftime("%d %B %Y", $qs[1]); + $text = " +
+
+ ".LAN_CONFDELETE." + + + + +
+ ".(($action == "confdel") ? RL_LAN_047 : RL_LAN_065).$old_string." +
+
+ + ".$frm->admin_button('confirmdeleteold', 'no-value', 'delete', RL_LAN_049)." + ".$frm->admin_button('confirmcancelold', 'no-value', 'delete', LAN_CANCEL)." +
+
+
+ + "; + + $ns->tablerender(LAN_CONFDELETE, $text); +} + +// Arrays of options for the various logs - the $page_title array is used to determine the allowable values for $action ('options' is a special case) +$log_db_table = array('adminlog' => 'admin_log', 'auditlog' => 'audit_log', 'rolllog' => 'dblog', 'downlog' => 'download_requests', 'online' => 'online'); +$back_day_count = array('adminlog' => 30, 'auditlog' => 30, 'rolllog' => max(intval($pref['roll_log_days']), 1), 'downlog' => 60, 'detailed' => 20, 'online' => 30); +$page_title = array('adminlog' => RL_LAN_030, 'auditlog' => RL_LAN_062, 'rolllog' => RL_LAN_002, 'downlog' => RL_LAN_067, 'detailed' => RL_LAN_094, 'online' => RL_LAN_120); + +// Set all the defaults for the data filter +$start_enabled = FALSE; +$end_enabled = FALSE; +$start_time = 0; +$end_time = 0; +$user_filter = ''; +$event_filter = ''; +$pri_filter_cond = "xx"; +$pri_filter_val = ""; +$sort_order = "DESC"; +$downloadid_filter = ''; + +$last_noted_time = 0; + +// Maintain the log view filter across pages +$rl_cookiename = $pref['cookie_name']."_rl_admin"; +if(isset($_POST['updatefilters']) || isset($_POST['clearfilters'])) +{ // Need to put the filter values into the cookie + if(! isset($_POST['clearfilters'])) + { // Only update filter values from $_POST[] if 'clear filters' not active + $start_time = intval($_POST['starttimedate'] + $_POST['starttimehours'] * 3600 + $_POST['starttimemins'] * 60); + $start_enabled = isset($_POST['start_enabled']); + if(isset($_POST['timelength'])) + { + $end_time = intval($_POST['timelength']) * 60 + $start_time; + } + else + { + $end_time = intval($_POST['endtimedate'] + $_POST['endtimehours'] * 3600 + $_POST['endtimemins'] * 60); + } + $end_enabled = isset($_POST['end_enabled']); + $user_filter = trim(varset($_POST['roll_user_filter'], '')); + if($user_filter != '') + $user_filter = intval($user_filter); + $event_filter = $tp->toDB($_POST['roll_event_filter']); + $pri_filter_cond = $tp->toDB($_POST['roll_pri_cond']); + $pri_filter_val = $tp->toDB($_POST['roll_pri_val']); + $caller_filter = $tp->toDB($_POST['roll_caller_filter']); + $ipaddress_filter = $e107->ipEncode($tp->toDB($_POST['roll_ipaddress_filter'])); + $downloadid_filter = $tp->toDB($_POST['roll_downloadid_filter']); + } + $cookie_string = implode("|", array($start_time, $start_enabled, $end_time, $end_enabled, $user_filter, $event_filter, $pri_filter_cond, $pri_filter_val, $caller_filter, $ipaddress_filter, $downloadid_filter)); + // echo $cookie_string."
"; + // Create session cookie to store values + cookie($rl_cookiename, $cookie_string, 0); // Use session cookie +} +else +{ + // Now try and get the filters from the cookie + if(isset($_COOKIE[$rl_cookiename])) + list($start_time, $start_enabled, $end_time, $end_enabled, $user_filter, $event_filter, $pri_filter_cond, $pri_filter_val, $caller_filter, $ipaddress_filter, $downloadid_filter) = explode("|", $_COOKIE[$rl_cookiename]); + if(isset($qs[1]) && isset($qs[2]) && ($qs[1] == 'user') && (intval($qs[2]) > 0)) + { + $user_filter = intval($qs[2]); + } +} + +$timelength = 5; +if($start_time != 0 && $end_time != 0) + $timelength = intval(($end_time - $start_time) / 60); + +function time_box($boxname, $this_time, $day_count, $inc_tomorrow = FALSE, $all_mins = FALSE) +{ // Generates boxes for date and time for today and the preceding days + // Appends 'date', 'hours', 'mins' to the specified boxname + + + $all_time = getdate(); // Date/time now + $sel_time = getdate($this_time); // Currently selected date/time + $sel_day = mktime(0, 0, 0, $sel_time['mon'], $sel_time['mday'], $sel_time['year']); + $today = mktime(0, 0, 0, $all_time['mon'], $all_time['mday'] + ($inc_tomorrow ? 1 : 0), $all_time['year']); + + // Start with day + $ret = ""; + + // Hours + $ret .= " "; + + // Minutes + $ret .= " "; + + return $ret; +} + +if(! defined("USER_WIDTH")) +{ + define("USER_WIDTH", "width:97%"); +} + +//==================================================================== +// CONFIGURATION OPTIONS MENU +//==================================================================== + +/* +if($action == "config") +{ + // User Audit log options (for info) + //======================= + // define('USER_AUDIT_SIGNUP',11); // User signed up + // define('USER_AUDIT_EMAILACK',12); // User responded to registration email + // define('USER_AUDIT_LOGIN',13); // User logged in + // define('USER_AUDIT_LOGOUT',14); // User logged out + // define('USER_AUDIT_NEW_DN',15); // User changed display name + // define('USER_AUDIT_NEW_PW',16); // User changed password + // define('USER_AUDIT_NEW_EML',17); // User changed email + // define('USER_AUDIT_NEW_SET',19); // User changed other settings (intentional gap in numbering) + // define('USER_AUDIT_ADD_ADMIN', 20); // User added by admin + // define('USER_AUDIT_MAIL_BOUNCE', 21); // User mail bounce + // define('USER_AUDIT_BANNED', 22); // User banned + // define('USER_AUDIT_BOUNCE_RESET', 23); // User bounce reset + // define('USER_AUDIT_TEMP_ACCOUNT', 24); // User temporary account + + + $audit_checkboxes = array(USER_AUDIT_SIGNUP => RL_LAN_071, USER_AUDIT_EMAILACK => RL_LAN_072, USER_AUDIT_LOGIN => RL_LAN_073, // USER_AUDIT_LOGOUT => RL_LAN_074, // Logout is lumped in with login + USER_AUDIT_NEW_DN => RL_LAN_075, USER_AUDIT_NEW_PW => RL_LAN_076, USER_AUDIT_PW_RES => RL_LAN_078, USER_AUDIT_NEW_EML => RL_LAN_077, USER_AUDIT_NEW_SET => RL_LAN_079, + USER_AUDIT_ADD_ADMIN => RL_LAN_080, USER_AUDIT_MAIL_BOUNCE => RL_LAN_081, USER_AUDIT_BANNED => RL_LAN_082, USER_AUDIT_BOUNCE_RESET => RL_LAN_083, + USER_AUDIT_TEMP_ACCOUNT => RL_LAN_084); + + if(! isset($e_userclass) && ! is_object($e_userclass)) + { + require_once (e_HANDLER."userclass_class.php"); + $e_userclass = new user_class(); + } + + $user_signup_opts = array_flip(explode(',', varset($pref['user_audit_opts'], ''))); + + // Common to all logs + $text = " +
+ ".RL_LAN_121." +
+
+ ".RL_LAN_122." + + + + + + + + + + + "; + + // User Audit Trail Options + $text .= " + + + + + + + + + "; + + + // Rolling log options + //==================== + $text .= " + + + + + + + + + +
".RL_LAN_044."".$frm->select('sys_log_perpage', array(10, 20, 30, 40, 50), $pref['sys_log_perpage'])."".RL_LAN_064."
".RL_LAN_123." + + ".RL_LAN_026." +
".RL_LAN_031.""; + + foreach($audit_checkboxes as $k => $t) + { + $checked = isset($user_signup_opts[$k]) ? true : false; + $text .= $frm->checkbox('user_audit_opts[]',$k, $checked, array('label'=>$t)); + } + + + $text .= $frm->admin_button('check_all', 'jstarget:user_audit_opts', 'checkall', LAN_CHECKALL).$frm->admin_button('uncheck_all', 'jstarget:user_audit_opts', 'checkall', LAN_UNCHECKALL)." +
".RL_LAN_008." +
+ ".$frm->checkbox('roll_log_active', 1, varset($pref['roll_log_active'],0))." +
+
".RL_LAN_009."".$frm->text('roll_log_days', $pref['roll_log_days'], 5)."
+
+ ".$frm->admin_button('setoptions', 'no-value', 'update', LAN_UPDATE)." +
+
+
+ "; + + // Admin log maintenance + //================== + $text .= " +
+
+ ".RL_LAN_125." + + + + + + + + + + + "; + + // User log maintenance + //==================== + $text .= " + + + + + +
".RL_LAN_045." ".gen_log_delete('rolllog_clearadmin')." ".RL_LAN_046.$frm->admin_button('deleteoldadmin', 'no-value', 'delete', RL_LAN_049)."
".RL_LAN_066." ".gen_log_delete('rolllog_clearaudit')." ".RL_LAN_046.$frm->admin_button('deleteoldaudit', 'no-value', 'delete', RL_LAN_049)."
+
+
+ +
+ "; + + $ns->tablerender(ADLAN_155.SEP.LAN_OPTIONS, $mes->render().$text); +} +*/ + +//==================================================================== +// LOG VIEW MENU +//==================================================================== +if(isset($page_title[$action])) +{ + $from = intval(varset($qs[1], 0)); // First entry to display + $amount = max(varset($pref['sys_log_perpage'], 20), 5); // Number of entries per page + + + // Array decides which filters are active for each log. There are 4 columns total. All but 'datetimes' occupy 2. Must specify multiple of 4 columns - add 'blank' if necessary + $active_filters = array( + 'adminlog' => array('datetimes' => 0, 'ipfilter' => 0, 'userfilter' => 0, 'eventfilter' => 0, 'priority' => 0), + 'auditlog' => array('datetimes' => 0, 'ipfilter' => 0, 'userfilter' => 0, 'eventfilter' => 0, 'blank' => 2), + 'rolllog' => array('datetimes' => 0, 'ipfilter' => 0, 'userfilter' => 0, 'eventfilter' => 0, 'priority' => 0, 'callerfilter' => 0, 'blank' => 2), + 'downlog' => array('datetimes' => 0, 'ipfilter' => 0, 'userfilter' => 0, 'downloadidfilter' => 0, 'blank' => 2), + 'detailed' => array('datestart' => 0, 'ipfilter' => 0, 'userfilter' => 0, 'eventfilter' => 0, 'blank' => 2), + 'online' => array('ipfilter' => 0, 'userfilter' => 0)); + + // Arrays determine column widths, headings, displayed fields for each log + $col_fields = array( + 'adminlog' => array('cf_datestring', 'dblog_type', 'dblog_ip', 'dblog_user_id', 'user_name', 'dblog_eventcode', 'dblog_title', 'dblog_remarks'), + 'auditlog' => array('cf_datestring', 'dblog_ip', 'dblog_user_id', 'dblog_user_name', 'dblog_eventcode', 'dblog_title', 'dblog_remarks'), + 'rolllog' => array('cf_datestring', 'dblog_type', 'dblog_ip', 'dblog_user_id', 'dblog_user_name', 'dblog_eventcode', 'dblog_caller', 'dblog_title', 'dblog_remarks'), + 'downlog' => array('cf_datestring', 'dblog_ip', 'dblog_user_id', 'user_name', 'download_request_download_id', 'download_name'), + 'detailed' => array('cf_microtime', 'cf_microtimediff', 'source', 'dblog_type', 'dblog_ip', 'dblog_user_id', 'user_name', 'dblog_eventcode', 'dblog_title', 'dblog_remarks'), + 'online' => array('cf_datestring', 'dblog_ip', 'dblog_user_id', 'user_name', 'online_location', 'online_pagecount', 'online_flag', 'online_active')); + $col_widths = array( + 'adminlog' => array(18, 4, 14, 7, 15, 8, 14, 20), // Date - Pri - IP - UID - User - Code - Event - Info + 'auditlog' => array(18, 14, 7, 15, 8, 14, 24), + 'rolllog' => array(15, 4, 12, 6, 12, 7, 13, 13, 18), // Date - Pri - IP - UID - User - Code - Caller - Event - Info + 'downlog' => array(18, 14, 7, 15, 8, 38), + 'detailed' => array(10, 8, 6, 4, 14, 6, 17, 7, 17, 21), + 'comments' => array(14, 7, 7, 7, 14, 3, 10, 12, 5, 17, 1, 1, 1), + 'online' => array(18, 15, 7, 14, 32, 6, 4, 4)); + $col_titles = array( + 'adminlog' => array(RL_LAN_019, RL_LAN_032, RL_LAN_020, RL_LAN_104, LAN_USER, RL_LAN_023, LAN_TITLE, RL_LAN_033), + 'auditlog' => array(RL_LAN_019, RL_LAN_020, RL_LAN_104, LAN_USER, RL_LAN_023, LAN_TITLE, RL_LAN_033), + 'rolllog' => array(RL_LAN_019, RL_LAN_032, RL_LAN_020, RL_LAN_104, LAN_USER, RL_LAN_023, RL_LAN_024, LAN_TITLE, RL_LAN_033), + 'downlog' => array(RL_LAN_019, RL_LAN_020, RL_LAN_104, LAN_USER, RL_LAN_068, RL_LAN_069), + 'detailed' => array(LAN_TIME, RL_LAN_096, LAN_SOURCE, RL_LAN_032, RL_LAN_020, RL_LAN_104, LAN_USER, RL_LAN_023, LAN_TITLE, RL_LAN_033), + 'online' => array(RL_LAN_019, RL_LAN_020, LAN_ID, LAN_USER, RL_LAN_116, RL_LAN_117, RL_LAN_118, RL_LAN_116)); + + + + // Only need to define entries in this array if the base DB query is non-standard (i.e. different field names and/or joins) + $base_query = array('downlog' => "SELECT SQL_CALC_FOUND_ROWS + dbl.download_request_id as dblog_id, + dbl.download_request_userid as dblog_user_id, + dbl.download_request_ip as dblog_ip, + dbl.download_request_download_id, + dbl.download_request_datestamp as dblog_datestamp, + d.download_name, + u.user_name + FROM #download_requests AS dbl + LEFT JOIN #user AS u ON dbl.download_request_userid=u.user_id + LEFT JOIN #download AS d ON dbl.download_request_download_id=d.download_id + ", 'detailed' => "SELECT SQL_CALC_FOUND_ROWS cl.*, u.* FROM ( + SELECT dblog_datestamp + (dblog_microtime/1000000) AS dblog_time, dblog_user_id, dblog_eventcode, dblog_title, dblog_remarks, dblog_type, dblog_ip, 'roll' AS source FROM `#dblog` + UNION + SELECT dblog_datestamp + (dblog_microtime/1000000) AS dblog_time, dblog_user_id, dblog_eventcode, dblog_title, dblog_remarks, '-' AS dblog_type, dblog_ip, 'audit' AS source FROM `#audit_log` + UNION + SELECT dblog_datestamp + (dblog_microtime/1000000) AS dblog_time, dblog_user_id, dblog_eventcode, dblog_title, dblog_remarks, dblog_type, dblog_ip, 'admin' AS source FROM `#admin_log`) AS cl + LEFT JOIN `#user` AS u ON cl.dblog_user_id=u.user_id ", 'comments' => "SELECT SQL_CALC_FOUND_ROWS *, comment_datestamp AS dblog_datestamp FROM `#comments` AS c", 'online' => "SELECT SQL_CALC_FOUND_ROWS online_timestamp AS dblog_datestamp, + online_ip AS dblog_ip, + SUBSTRING_INDEX(online_user_id,'.',1) AS dblog_user_id, + SUBSTRING(online_user_id FROM LOCATE('.',online_user_id)+1) AS user_name, + `online_location`, `online_pagecount`, `online_flag`, `online_active` + FROM `#online`"); + + // The filters have to use the 'actual' db field names. So the following table sets the defaults and the exceptions which vary across the range of tables supported + $map_filters = array('default' => array('datetimes' => '`dblog_datestamp`', 'ipfilter' => '`dblog_ip`', 'userfilter' => '`dblog_user_id`', 'eventfilter' => '`dblog_eventcode`'), 'downlog' => array('datetimes' => '`download_request_datestamp`', 'ipfilter' => '`download_request_ip`', 'userfilter' => '`download_request_userid`'), 'detailed' => array('datestart' => '`dblog_time`'), 'comments' => array('datetimes' => '`comment_datestamp`', 'ipfilter' => '`comment_ip`', 'eventfilter' => 'comment_type', 'userfilter' => '`comment_author_id`'), 'online' => array('online_ip' => '`dblog_ip`', 'online_user_id' => '`dblog_user_id`')); + + // Field to sort table on + $sort_fields = array('default' => 'dblog_id', 'detailed' => 'dblog_time', 'comments' => 'comment_datestamp', 'online' => 'online_timestamp'); + + // Check things + if($start_time >= $end_time) + { // Make end time beginning of tomorrow + $tempdate = getdate(); + $end_time = mktime(0, 0, 0, $tempdate['mon'], $tempdate['mday'] + 1, $tempdate['year']); // Seems odd, but mktime will work this out OK + // (or so the manual says) + } + + // Now work out the query - only use those filters which are displayed + $qry = ''; + $and_array = array(); + foreach($active_filters[$action] as $fname => $fpars) + { + $filter_field = varset($map_filters[$action][$fname], $map_filters['default'][$fname]); + switch($fname) + { + case 'datetimes': + if($start_enabled && ($start_time > 0)) + $and_array[] = "{$filter_field} >= ".intval($start_time); + if($end_enabled && ($end_time > 0)) + $and_array[] = "{$filter_field} <= ".intval($end_time); + break; + case 'datestart': + if($start_time == 0) + { + $end_time = time(); + $start_time = $end_time - 300; // Default to last 5 mins + } + $and_array[] = "{$filter_field} >= ".intval($start_time); + $and_array[] = "{$filter_field} <= ".intval($end_time); + break; + case 'ipfilter': + if($ipaddress_filter != "") + { + if(substr($ipaddress_filter, - 1) == '*') + { // Wildcard to handle - mySQL uses % + $and_array[] = "{$filter_field} LIKE '".substr($ipaddress_filter, 0, - 1)."%' "; + } + else + { + $and_array[] = "{$filter_field}= '".$ipaddress_filter."' "; + } + } + break; + case 'userfilter': + if($user_filter != '') + $and_array[] = "{$filter_field} = ".intval($user_filter); + break; + case 'eventfilter': + if($event_filter != '') + { + if(substr($event_filter, - 1) == '*') + { // Wildcard to handle - mySQL uses % + $and_array[] = " {$filter_field} LIKE '".substr($event_filter, 0, - 1)."%' "; + } + else + { + $and_array[] = "{$filter_field}= '".$event_filter."' "; + } + } + break; + case 'callerfilter': + if($caller_filter != '') + { + if(substr($caller_filter, - 1) == '*') + { // Wildcard to handle - mySQL uses % + $and_array[] = "dblog_caller LIKE '".substr($caller_filter, 0, - 1)."%' "; + } + else + { + $and_array[] = "dblog_caller= '".$caller_filter."' "; + } + } + break; + case 'priority': + if(($pri_filter_val != "") && ($pri_filter_cond != "") && ($pri_filter_cond != "xx")) + { + switch($pri_filter_cond) + { + case "lt": + $and_array[] = "dblog_type <= '{$pri_filter_val}' "; + break; + case "eq": + $and_array[] = "dblog_type = '{$pri_filter_val}' "; + break; + case "gt": + $and_array[] = "dblog_type >= '{$pri_filter_val}' "; + break; + } + } + break; + case 'downloadidfilter': + if($downloadid_filter != '') + $and_array[] = "download_request_download_id = ".intval($downloadid_filter); + break; + } + } + + if(count($and_array)) + $qry = " WHERE ".implode(' AND ', $and_array); + + $limit_clause = " LIMIT {$from}, {$amount} "; + $sort_field = varset($sort_fields[$action], $sort_fields['default']); + + if(isset($base_query[$action])) + { + $qry = $base_query[$action].$qry." ORDER BY {$sort_field} ".$sort_order; + } + else + { + $qry = "SELECT SQL_CALC_FOUND_ROWS dbl.*,u.user_name FROM #".$log_db_table[$action]." AS dbl LEFT JOIN #user AS u ON dbl.dblog_user_id=u.user_id".$qry." ORDER BY {$sort_field} ".$sort_order; + } + + $num_entry = 0; + if($sql->gen($qry.$limit_clause)) + { + $num_entry = $sql->total_results; + } + if($from > $num_entry) + { + $from = 0; // We may be on a later page + $limit_clause = " LIMIT {$from}, {$amount} "; + $sql->gen($qry.$limit_clause); // Re-run query with new value of $from + $num_entry = $sql->total_results; + } + + // Start by putting up the filter boxes + $text = " +
+
+ ".RL_LAN_012." + + + + + + + + "; + $filter_cols = 0; + foreach($active_filters[$action] as $fname => $fpars) + { + if($filter_cols == 0) + $text .= ''; + switch($fname) + { + case 'datetimes': + $text .= " + + + + + "; + $filter_cols = 4; + break; + case 'datestart': + $text .= " + + + + "; + $filter_cols = 4; + break; + case 'priority': + $text .= " + + + "; + $filter_cols += 2; + break; + case 'ipfilter': + $text .= " + + + "; + $filter_cols += 2; + break; + case 'userfilter': + $text .= " + + + "; + $filter_cols += 2; + break; + case 'eventfilter': + $text .= " + + + "; + $filter_cols += 2; + break; + case 'callerfilter': + $text .= " + + + "; + $filter_cols += 2; + break; + case 'downloadidfilter': + $text .= " + + "; + $filter_cols += 2; + break; + case 'blank': // Any number of blank cells + $text .= str_repeat("", $fpars); + $filter_cols += $fpars; + break; + } + if($filter_cols >= 4) + { + $text .= ''; + $filter_cols = 0; + } + } + + // $text .= ""; + $text .= " +
".$frm->checkbox('start-enabled', 1, varset($pref['start-enabled'],0))."".time_box("starttime", $start_time, $back_day_count[$action], FALSE)."".$frm->checkbox('end-enabled', 1, varset($pref['end-enabled'],0))."".time_box("endtime", $end_time, $back_day_count[$action], TRUE)."".RL_LAN_013."".time_box("starttime", $start_time, $back_day_count[$action], FALSE, TRUE)."".RL_LAN_092." + ".RL_LAN_093." + ".RL_LAN_058."".$frm->select('roll_pri_cond', array('xx' => ' ', 'gt' => '>=', 'eq' => '==', 'lt' => '<='), $pri_filter_cond)." + + ".RL_LAN_060." + + ".RL_LAN_061." + ".RL_LAN_015." + + ".RL_LAN_016." + ".RL_LAN_029." + + ".RL_LAN_061." + ".RL_LAN_059." + + ".RL_LAN_061." + ".RL_LAN_090." + +  
Query = ".$qry.$limit_clause."
{$_COOKIE[$rl_cookiename]}
+
+ ".$frm->admin_button('clearfilters', 'no-value', 'delete', RL_LAN_114)." + ".$frm->admin_button('updatefilters', 'no-value', 'update', RL_LAN_028)." +
+
+
+ "; + + // Next bit is the actual log display - the arrays define column widths, titles, fields etc for each log + $column_count = count($col_widths[$action]); + $text .= " +
+
+ {$page_title[$action]} + + + "; + + foreach($col_widths[$action] as $i) + { + $text .= " + + "; + } + + $text .= " + + + "; + + if($num_entry == 0) + { + $text .= " + + + + "; + } + else + { // Start with header + $text .= ' + + + '; + $count = 1; + foreach($col_titles[$action] as $ct) + { + count($col_titles[$action]); + $text .= " + {$ct} + "; + $count ++; + } + $text .= " + + + + "; + + // Routine to handle the simple bbcode-like codes for log body text + function log_process($matches) + { + switch($matches[1]) + { + case 'br': + return '
'; + case 'link': + $temp = substr($matches[2], 1); + return "{$temp}"; + case 'test': + return '----TEST----'; + default: + return $matches[0]; // No change + } + } + // Now put up the events + $delete_button = FALSE; + while($row = $sql->db_Fetch()) + { + $text .= ''; + foreach($col_fields[$action] as $cf) + { + switch($cf) + { + case 'cf_datestring': + $val = date(AL_DATE_TIME_FORMAT, $row['dblog_datestamp']); + break; + case 'cf_microtime': + $val = date("H:i:s", intval($row['dblog_time']) % 86400).'.'.str_pad(100000 * round($row['dblog_time'] - floor($row['dblog_time']), 6), 6, '0'); + break; + case 'cf_microtimediff': + $val = ' '; + if($last_noted_time > 0) + { + $val = number_format($last_noted_time - $row['dblog_time'], 6, '.', ''); + } + $last_noted_time = $row['dblog_time']; + break; + case 'cf_eventcode': + $val = 'ADMIN'.$row['dblog_eventcode']; + break; + case 'dblog_title': // Look up constants to give multi-language viewing + $val = trim($row['dblog_title']); + if(defined($val)) + $val = constant($val); + break; + case 'dblog_user_name': + $val = $row['dblog_user_id'] ? $row['dblog_user_name'] : LAN_ANONYMOUS; + break; + case 'user_name': + $val = $row['dblog_user_id'] ? $row['user_name'] : LAN_ANONYMOUS; + break; + case 'dblog_caller': + $val = $row['dblog_caller']; + if((strpos($val, '|') !== FALSE) && (strpos($val, '@') !== FALSE)) + { + list($file, $rest) = explode('|', $val); + list($routine, $rest) = explode('@', $rest); + $val = $file.'
Function: '.$routine.'
Line: '.$rest; + } + break; + case 'dblog_remarks': + // Look for pseudo-code for newlines, link insertion + $val = preg_replace_callback("#\[!(\w+?)(=.+?){0,1}!]#", 'log_process', $row['dblog_remarks']); + break; + case 'dblog_ip': + $val = e107::getIPHandler()->ipDecode($row['dblog_ip']); + break; + case 'comment_ip': + $val = e107::getIPHandler()->ipDecode($row['comment_ip']); + /* if (strlen($val) == 8) // New decoder should handle this automatically + { + $hexip = explode('.', chunk_split($val, 2, '.')); + $val = hexdec($hexip[0]). '.'.hexdec($hexip[1]).'.'.hexdec($hexip[2]).'.'.hexdec($hexip[3]); + } */ + break; + case 'comment_comment': + $val = $tp->text_truncate($row['comment_comment'], 100, '...'); // Just display first bit of comment + break; + case 'online_location': + $val = str_replace($e107->base_path, '', $row['online_location']); // Just display site-specific bit of path + break; + case 'del_check': // Put up a 'delete' checkbox + $val = ""; + $delete_button = TRUE; + break; + default: + $val = $row[$cf]; + } + $text .= ""; + } + $text .= ""; + } + } + $text .= " + +
".RL_LAN_017."
{$val}
+
+ ".$frm->admin_button('refreshlog', 'no-value', 'submit', RL_LAN_018)." + "; + if($delete_button) + { + $text .= $frm->admin_button('deleteitems', 'no-value', 'delete', RL_LAN_11); + } + $text .= " +
+
+
+ "; + + // Next-Previous. ========================== + + $text .= sprintf(str_replace("[x]", "%d", RL_LAN_126), $num_entry); + if($num_entry > $amount) + { + $parms = "{$num_entry},{$amount},{$from},".e_SELF."?".$action.".[FROM]"; + $text .= "
".$tp->parseTemplate("{NEXTPREV={$parms}}")."
"; + } + + $ns->tablerender("{$page_title[$action]}", $mes->render().$text); +} + +function admin_log_adminmenu() +{ + if(e_QUERY) + { + $tmp = explode(".", e_QUERY); + $action = $tmp[0]; + } + if($action == "") + { + $action = "adminlog"; + } + $var['adminlog']['text'] = RL_LAN_030; + $var['adminlog']['link'] = "admin_log.php?adminlog"; + + $var['auditlog']['text'] = RL_LAN_062; + $var['auditlog']['link'] = "admin_log.php?auditlog"; + + $var['rolllog']['text'] = RL_LAN_002; + $var['rolllog']['link'] = "admin_log.php?rolllog"; + + $var['downlog']['text'] = RL_LAN_067; + $var['downlog']['link'] = "admin_log.php?downlog"; + + $var['detailed']['text'] = RL_LAN_091; + $var['detailed']['link'] = "admin_log.php?detailed"; + +// Deprecated by Comments Manager. +/* + $var['comments']['text'] = 'Comments'; + $var['comments']['link'] = "admin_log.php?comments"; +*/ + $var['config']['text'] = LAN_OPTIONS; + $var['config']['link'] = "admin_log.php?config"; + + /* XXX - why?! + if($action == 'comments') + { + $var['users']['text'] = RL_LAN_115; + $var['users']['link'] = "users.php"; + } + */ + e107::getNav()->admin(RL_LAN_005, $action, $var); +} + +require_once (e_ADMIN."footer.php"); + + + +/** + * Handle page DOM within the page header + * + * @return string JS source + *//* +function headerjs() +{ + require_once(e_HANDLER.'js_helper.php'); + $ret = " + + + "; + + return $ret; +}*/ + +?> diff --git a/e107_admin/cron.php b/e107_admin/cron.php index 25289447d..5b61e19d1 100644 --- a/e107_admin/cron.php +++ b/e107_admin/cron.php @@ -1,1289 +1,1289 @@ - array( - 'controller' => 'cron_admin_ui', - 'path' => null, - 'ui' => 'cron_admin_form_ui', - 'uipath' => null - ) - ); - - - protected $adminMenu = array( - 'main/list' => array('caption'=> LAN_MANAGE, 'perm' => '0'), - 'main/refresh' => array('caption'=> LAN_CRON_M_02, 'perm' => '0','url'=>'cron.php'), - // 'main/prefs' => array('caption'=> 'Settings', 'perm' => '0'), - // 'main/custom' => array('caption'=> 'Custom Page', 'perm' => '0') - ); - - protected $adminMenuAliases = array( - 'main/edit' => 'main/list' - ); - - protected $menuTitle = PAGE_NAME; - - protected $adminMenuIcon = 'e-cron-24'; - -} - -class cron_admin_ui extends e_admin_ui -{ - - protected $pluginTitle = PAGE_NAME; - protected $pluginName = 'core'; - protected $table = "cron"; - protected $pid = "cron_id"; - protected $listOrder = 'cron_category desc'; // Show 'upgrades' on first page. - protected $perPage = 10; - protected $batchDelete = TRUE; - - protected $fields = array( - 'checkboxes' => array('title'=> '', 'type' => null, 'width' =>'5%', 'forced'=> TRUE, 'thclass'=>'center', 'class'=>'center'), - 'cron_id' => array('title'=> LAN_ID, 'type' => 'number', 'width' =>'5%', 'forced'=> FALSE, 'nolist'=>TRUE), - 'cron_category' => array('title'=> LAN_CATEGORY, 'type' => 'method', 'data' => 'str', 'width'=>'auto','readonly' => 1, 'thclass' => '', 'batch' => TRUE, 'filter'=>TRUE), - 'cron_name' => array('title'=> LAN_NAME, 'type' => 'text', 'data'=>'str', 'width' => 'auto', 'readonly' => 1), - 'cron_description' => array('title'=> LAN_DESCRIPTION, 'type' => 'text', 'data'=>'str', 'width' => '35%', 'readonly' => 1), - 'cron_function' => array('title'=> LAN_CRON_2, 'type' => 'text', 'data'=>'str', 'width' => 'auto', 'thclass' => 'left first', 'readonly' => 1), - 'cron_tab' => array('title'=> LAN_CRON_3, 'type' => 'method', 'width' => 'auto'), // Display name - 'cron_lastrun' => array('title'=> LAN_CRON_4, 'type' => 'datestamp', 'data' => 'int', 'width' => 'auto', 'readonly' => 2), - 'cron_active' => array('title'=> LAN_ACTIVE, 'type' => 'boolean', 'data'=> 'int', 'thclass' => 'center', 'class'=>'center', 'filter' => true, 'batch' => true, 'width' => 'auto'), - 'options' => array('title'=> LAN_OPTIONS, 'type' => 'method', 'data'=> null, 'noedit'=>TRUE, 'forced'=>TRUE, 'width' => '10%', 'thclass' => 'center last', 'class' => 'right') - ); - - - // public function beforeCreate($new_data) - // { - - // } - private $curCrons = array(); - private $activeCrons = 0; - - function init() - { - $pref = e107::getPref(); - $sql = e107::getDb(); - - if(vartrue($_POST['cron_execute'])) - { - $executeID = key($_POST['cron_execute']); - $this->cronExecute($executeID); - } - - - if (!vartrue(e107::getPref('e_cron_pwd')) || varset($_POST['generate_pwd'])) - { - $pwd = $this->setCronPwd(); - } - - $sql->gen("SELECT cron_function,cron_active FROM #cron "); - while($row = $sql->fetch()) - { - $this->curCrons[] = $row['cron_function']; - if($row['cron_active']==1) - { - $this->activeCrons++; - } - } - - $this->lastRefresh(); - // Import Core and Plugin e_cron data - - $cronDefaults['_system'] = array( - 0 => array( - 'name' => LAN_CRON_01_1, - 'function' => 'sendEmail', - 'category' => 'mail', - 'description' => str_replace("[eml]",$pref['siteadminemail'],LAN_CRON_01_2) ."
". LAN_CRON_01_3 - ), - 1 => array( - 'name' => LAN_CRON_02_1, - 'category' => 'mail', - 'function' => 'procEmailQueue', - 'description' => LAN_CRON_02_2 - ), - 2 => array( - 'name' => LAN_CRON_03_1, - 'category' => 'mail', - 'function' => 'procEmailBounce', - 'description' => LAN_CRON_03_2 - // 'available' => vartrue($pref['mail_bounce_auto']) - ), - 3 => array( - 'name' => LAN_CRON_04_1, - 'category' => 'user', - 'function' => 'procBanRetrigger', - 'description' => LAN_CRON_04_2 ."
". LAN_CRON_04_3, - 'available' => e107::getPref('ban_retrigger') - ), - 4 => array( - 'name' => LAN_CRON_05_1, - 'category' => 'backup', - 'function' => 'dbBackup', - 'description' => LAN_CRON_05_2 .' '.e_SYSTEM.'backups/' - // 'available' => e107::getPref('ban_retrigger') - ), - 5 => array( - 'name' => LAN_CRON_06_1, - 'category' => 'user', - 'function' => 'procBanRetrigger', - 'description' => LAN_CRON_06_2 ."
". LAN_CRON_06_3, - // 'available' => e107::getPref('ban_retrigger') - ), - 6 => array( - 'name' => LAN_CRON_20_1, - 'category' => 'update', - 'function' => 'checkCoreUpdate', - 'description' => LAN_CRON_20_2 ."
". LAN_CRON_20_3, - // 'available' => e107::getPref('ban_retrigger') - ), - - ); - - if(is_dir(e_BASE.".git")) - { - $cronDefaults['_system'][7] = array( - 'name' => LAN_CRON_20_4, - 'category' => 'update', - 'function' => 'gitrepo', - 'description' => LAN_CRON_20_5."
".LAN_CRON_20_6."
".LAN_WARNING." ".LAN_CRON_20_8, - // 'available' => e107::getPref('ban_retrigger') - ); - - } - - - - - if(!vartrue($_GET['action']) || $_GET['action'] == 'refresh') - { - - $this->cronImport($cronDefaults); // import Core Crons (if missing) - $this->cronImport(e107::getAddonConfig('e_cron')); // Import plugin Crons - $this->cronImportLegacy(); // Import Legacy Cron Tab Settings - } - - $this->renderHelp(); - - } - - - - /** - * Import Cron Settings into Database. - */ - public function cronImport($new_cron = array()) - { - if(empty($new_cron)) - { - return null; - } - - $tp = e107::getParser(); - - foreach($new_cron as $class => $ecron) - { - foreach($ecron as $val) - { - $insert = array( - 'cron_id' => 0, - 'cron_name' => $val['name'], - 'cron_category' => $val['category'], - 'cron_description' => $tp->toDB($val['description']), - 'cron_function' => $class."::".$val['function'], - 'cron_tab' => varset($val['tab'], '* * * * *'), - 'cron_active' => varset($val['active'], '0'), - ); - - $this->cronInsert($insert); - } - } - } - - - - /** - * Import Legacy e_cron_pref settings. - */ - public function cronImportLegacy() - { - global $pref; - - $cronPref = e107::getPref('e_cron_pref'); - - - if(!is_array($cronPref)) - { - return; - } - - foreach($cronPref as $val) - { - $update = array( - 'cron_tab' => $val['tab'], - 'cron_active' => $val['active'], - 'cron_function' => $val['class']."::".$val['function'], - 'WHERE' => "cron_function = '".$val['class']."::".$val['function']."'" - ); - - $this->cronUpdate($update); - } - - e107::getConfig()->remove('e_cron_pref')->save(); - } - - - - - // Insert a Cron. - public function cronInsert($insert) - { - // print_a($insert); - // return; -// - $sql = e107::getDb(); - - if(in_array($insert['cron_function'],$this->curCrons)) - { - return; - } - - if(!$sql->insert('cron',$insert)) - { - e107::getMessage()->addDebug(LAN_CRON_6); - } - else - { - e107::getMessage()->add(LAN_CRON_8.": ".$insert['cron_function'], E_MESSAGE_INFO); - } - } - - - - /** - * Update cron timing - from legacy Pref. - */ - public function cronUpdate($insert) - { - // print_a($insert); - // return; - - $sql = e107::getDb(); - - $cron_function = $insert['cron_function']; - unset($insert['cron_function']); - - if($sql->update('cron',$insert)===FALSE) - { - e107::getMessage()->add(LAN_CRON_7, E_MESSAGE_ERROR); - } - else - { - e107::getMessage()->add(LAN_CRON_8.$cron_function, E_MESSAGE_INFO); - } - } - - - - - - // Process _POST before saving. - public function beforeUpdate($new_data, $old_data, $id) - { - $new_data['cron_tab'] = implode(" ", $new_data['tab']); - return $new_data; - } - - - function setCronPwd() - { - //global $pref; - $userMethods = e107::getUserSession(); - $newpwd = $userMethods->generateRandomString('*^*#.**^*'); - $newpwd = sha1($newpwd.time()); - - e107::getConfig()->set('e_cron_pwd', $newpwd)->save(false); - return true; - - } - - - - function lastRefresh() - { - $pref = e107::getPref(); - $mes = e107::getMessage(); - $frm = e107::getForm(); - - if(file_exists(e_CACHE.'cronLastLoad.php')) - { - $lastload = intval(@file_get_contents(e_CACHE.'cronLastLoad.php')); - } - else - { - $lastload = 0; - } - - $ago = (time() - $lastload); - - $active = ($ago < 1200) ? true : false; // longer than 20 minutes, so lets assume it's inactive. - $status = ($active) ? LAN_ENABLED : LAN_DISABLED; // "Enabled" : "Offline"; - - $mins = floor($ago / 60); - $secs = $ago % 60; - - $srch = array("[x]","[y]"); - $repl = array($mins,$secs); - - $lastRun = ($mins) ? str_replace($srch,$repl,LAN_CRON_9) : str_replace($srch,$repl,LAN_CRON_10); // FIX: check syntax - - $lastRefresh = ($ago < 10000) ? $lastRun : LAN_NEVER; - - $mes->addInfo(LAN_STATUS.": ".$status.""); - $mes->addInfo(LAN_CRON_11.": ".$this->activeCrons.""); - $mes->addInfo(LAN_CRON_12.": ".$lastRefresh."

"); - - - // extensions of exe, com, bat and cmd. - - $isWin = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; - $actualPerm = substr(decoct(fileperms(e_BASE."cron.php")),3); - - if($isWin) - { - $mes->addWarning(LAN_CRON_13); - } - if (!$isWin && $actualPerm != 755) // is_executable() is not reliable. - { - $mes->addWarning(LAN_CRON_14); - } - elseif (!$active) // show instructions - { - $setpwd_message = $frm->open("generate")."" - .LAN_CRON_15.":
".e_ROOT."cron.php token=".$pref['e_cron_pwd'].' >/dev/null 2>&1';
-				
-				$setpwd_message .= "
". LAN_CRON_16.""; - if(e_DOMAIN && file_exists("/usr/local/cpanel/version")) - { - $setpwd_message .= "
".LAN_CRON_60."
"; - - } - $setpwd_message .= "

".$frm->admin_button('generate_pwd', 1, 'delete', LAN_CRON_61 ,array('class'=>'btn btn-small')); - $setpwd_message .= $frm->close(); - - $mes->add($setpwd_message, E_MESSAGE_INFO); - } - - } - - function cronExecute($cron_id) - { - $sql = e107::getDb(); - if($sql->select("cron","cron_name,cron_function","cron_id = ".intval($cron_id))) - { - $row = $sql->fetch(); - $class_func = $row['cron_function']; - $cron_name = $row['cron_name']; - } - - if(!$class_func) - { - return; - } - - - list($class_name, $method_name) = explode("::", $class_func); - $mes = e107::getMessage(); - $taskName = $class_name; - - if ($class_name == '_system') - { - require_once(e_HANDLER.'cron_class.php'); - } - else - { - require_once(e_PLUGIN.$class_name.'/e_cron.php'); - } - $class_name .= '_cron'; - $status = $this->cronExecuteMethod($class_name, $method_name) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR; - $mes->add(LAN_CRON_RUNNING.":".$cron_name."", $status); - } - - - - function cronExecuteMethod($class_name, $method_name, $return = 'boolean') - { - $mes = e107::getMessage(); - - if (class_exists($class_name)) - { - $obj = new $class_name; - if (method_exists($obj, $method_name)) - { - $message = str_replace('[x]', $class_name." : ".$method_name, LAN_CRON_62);//Executing config function [b][x][/b] - $message = e107::getParser()->toHTML($message,true); - $mes->add($message, E_MESSAGE_DEBUG); - if ($return == 'boolean') - { - call_user_func(array($obj, $method_name)); - return TRUE; - } - else - { - return call_user_func(array($obj, $method_name)); - } - } - else - { - $message = str_replace('[x]', $method_name."()", LAN_CRON_63 );//Config function [b][x][/b] NOT found. - $message = e107::getParser()->toHTML($message,true); - $mes->add($message, E_MESSAGE_DEBUG); - } - } - return FALSE; - } - - function renderHelp() - { - return array('caption'=>LAN_HELP, 'text'=>e107::getParser()->toHTML(LAN_CRON_64, true)); - } - -} - -class cron_admin_form_ui extends e_admin_form_ui -{ - - var $min_options = array( - "*" => LAN_CRON_30, - "0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58" => LAN_CRON_31, - "0,5,10,15,20,25,30,35,40,45,50,55" => LAN_CRON_32, - "0,10,20,30,40,50" => LAN_CRON_33, - "0,15,30,45" => LAN_CRON_34, - "0,30" => LAN_CRON_35 - ); - - var $hour_options = array( - "*" => LAN_CRON_36, - "0,2,4,6,8,10,12,14,16,18,20,22" => LAN_CRON_37, - "0,3,6,9,12,15,18,21" => LAN_CRON_38, - "0,6,12,18" => LAN_CRON_39 - ); - - - var $cronCategories = array( - 'backup' => LAN_CRON_BACKUP, - 'content' => ADLAN_CL_3, - 'log' => LAN_CRON_LOGGING, - 'mail' => ADLAN_136, - 'notify' => ADLAN_149, - 'user' => LAN_USER, - 'plugin' => ADLAN_CL_7, - 'update' => LAN_UPDATE - ); - - /** - * Render cron_tab field - */ - function cron_tab($curVal,$mode) - { - if($mode == 'read') - { - $sep = array(); - list($min, $hour, $day, $month, $weekday) = explode(" ", $curVal); - $text = (isset($this->min_options[$min])) ? $this->min_options[$min] : LAN_CRON_50 ." ". $min; // Minute(s) - $text .= "
"; - $text .= (isset($this->hour_options[$hour])) ? $this->hour_options[$hour] : LAN_CRON_51 ." ". $hour; // Hour(s) - $text .= "
"; - $text .= ($day != '*') ? LAN_CRON_52 ." ". $day : LAN_CRON_40; // Day(s) - $text .= "
"; - $text .= ($month != '*') ? LAN_CRON_53 ." ". strftime("%B", mktime(00, 00, 00, $month, 1, 2000)) : LAN_CRON_41; // Month(s) - $text .= "
"; - $text .= ($weekday != '*') ? LAN_CRON_54 ." ". strftime("%A", mktime(00, 00, 00, 5, $weekday, 2000)) : LAN_CRON_42; // Weekday(s) - - - return "".ADMIN_INFO_ICON." -
".$text."
"; - - return $text; - } - - if($mode == 'write') - { - return $this->editTab($curVal); - } - - if($mode == 'filter') // Custom Filter List - { - return; - } - - if($mode == 'batch') - { - return; - } - } - - - function cron_category($curVal,$mode) - { - if($mode == 'read') - { - return isset($this->cronCategories[$curVal]) ? $this->cronCategories[$curVal] : ""; - } - - if($mode == 'write') - { - return isset($this->cronCategories[$curVal]) ? $this->cronCategories[$curVal] : ""; - } - - if($mode == 'filter') - { - return $this->cronCategories; - } - if($mode == 'batch') - { - return; - } - } - - // Override the default Options field. - function options($parms, $value, $id, $attributes) - { - $att = $attributes; - if($attributes['mode'] == 'read') - { - $func = $this->getController()->getFieldVar('cron_function'); - // - if(substr($func,0,7) === '_system') - { - $att['readParms'] = array('disabled'=>'disabled'); - } - - $text = "
"; - $text .= $this->renderValue('options',$value,$att,$id); - $text .= $this->submit_image('cron_execute['.$id.']', 1, 'execute', LAN_RUN); - $text .= "
"; - - - return $text; - } - } - - - function editTab($curVal) - { - $sep = array(); - list($sep['minute'], $sep['hour'], $sep['day'], $sep['month'], $sep['weekday']) = explode(" ", $curVal); - - foreach ($sep as $key => $value) - { - if ($value == "") - { - $sep[$key] = "*"; - } - } - - $minute = explode(",", $sep['minute']); - $hour = explode(",", $sep['hour']); - $day = explode(",", $sep['day']); - $month = explode(",", $sep['month']); - $weekday = explode(",", $sep['weekday']); - - - - $text = " - - - - - - - - - "; - - return $text; - - } - - - - -} - -new cron_admin(); - - - -$e_sub_cat = 'cron'; - -require_once('auth.php'); - -e107::getAdminUI()->runPage(); -$frm = e107::getForm(); -// $cron = new cron(); - -require_once(e_ADMIN.'footer.php'); -exit; -/* -class cron -{ - protected $coreCrons = array(); - protected $cronAction; - protected $e_cron = array(); - - public function __construct() - { - $pref = e107::getPref(); - $mes = e107::getMessage(); - $this->cronAction = e_QUERY; - - // The 'available' flag only gives the option to configure the cron if the underlying feature is enabled - $this->coreCrons['_system'] = array( - 0 => array('name' => 'Test Email', 'function' => 'sendEmail', 'description' => 'Send a test email to '.$pref['siteadminemail'].'
Recommended to test the scheduling system.'), - 1 => array('name' => 'Mail Queue', 'function' => 'procEmailQueue', 'description' => 'Process mail queue'), - 2 => array('name' => 'Mail Bounce Check', 'function' => 'procEmailBounce', 'description' => 'Check for bounced emails', 'available' => vartrue($pref['mail_bounce_auto'])), - // 1 => array('name'=>'User Purge', 'function' => 'userPurge', 'description'=>'Purge Unactivated Users'), - // 2 => array('name'=>'User UnActivated', 'function' => 'userUnactivated', 'description'=>'Resend activation email to unactivated users.'), - // 3 => array('name'=>'News Sticky', 'function' => 'newsPurge', 'description'=>'Remove Sticky News Items') - ); - - if (!vartrue($pref['e_cron_pwd'])) - { - $pwd = $this->setCronPwd(); - } - - if (isset($_POST['submit'])) - { - $this->cronSave(); - } - - $this->lastRefresh(); - $this->cronLoad(); - - if (isset($_POST['save_prefs'])) - { - $this->cronSavePrefs(); - } - - if (isset($_POST['execute'])) - { - - $class_func = key($_POST['execute']); - $this->cronExecute($class_func); - } - - // Set Core Cron Options. - - // These core functions need to be put into e_BASE/cron.php ie. news_purge() - - if ($this->cronAction == "" || $this->cronAction == "main") - { - $this->cronRenderPage(); - } - - if ($this->cronAction == "pref") - { - $this->cronRenderPrefs(); - } - } - - function lastRefresh() - { - $pref = e107::getPref(); - e107::getCache()->CachePageMD5 = '_'; - $lastload = e107::getCache()->retrieve('cronLastLoad', FALSE, TRUE, TRUE); - $mes = e107::getMessage(); - $ago = (time() - $lastload); - - $active = ($ago < 901) ? TRUE : FALSE; - $status = ($active) ? LAN_ENABLED : LAN_DISABLED; // "Enabled" : "Offline"; - - $mins = floor($ago / 60); - $secs = $ago % 60; - - $lastRun = ($mins) ? $mins." minutes and ".$secs." seconds ago." : $secs." seconds ago."; - - $lastRefresh = ($ago < 10000) ? $lastRun : 'Never'; - - $mes->add("Status: ".$status."", E_MESSAGE_INFO); - - // print_a($pref['e_cron_pref']); - - if ($pref['e_cron_pref']) // grab cron - - { - foreach ($pref['e_cron_pref'] as $func => $cron) - { - if ($cron['active'] == 1) - { - $list[$func] = $cron; - } - } - } - - $mes->add("Active Crons: ".count($list)."", E_MESSAGE_INFO); - $mes->add("Last cron refresh: ".$lastRefresh, E_MESSAGE_INFO); - - //FIXME: for Windows, the is_executable() function only checks the file - // extensions of exe, com, bat and cmd. - - - $actualPerms = fileperms(e_BASE."cron.php"); - - if (!is_executable(realpath(e_BASE."cron.php"))) - { - $mes->add("Please CHMOD /cron.php to 755 ", E_MESSAGE_WARNING); - } - //elseif (!$active) - always show instructions - { - $setpwd_message = "Use the following Cron Command: ".$_SERVER['DOCUMENT_ROOT'].e_HTTP."cron.php ".$pref['e_cron_pwd']."
- Using your server control panel (eg. cPanel,Plesk etc.) please create a crontab to run this command on your server every minute."; - $mes->add($setpwd_message, E_MESSAGE_INFO); - } - - } - - function cronName($classname, $method) - { - $tp = e107::getParser(); - - foreach ($this->e_cron as $class => $val) - { - - if ($class == $classname) - { - foreach ($val as $func) - { - if ($func['function'] == $method) - { - return $tp->toHTML($func['name']); - } - } - } - } - } - - function cronExecute($class_func) - { - //TO/ DO L/ANs - list($class_name, $method_name) = explode("__", $class_func); - $mes = e107::getMessage(); - - $taskName = $class_name; - if ($class_name == '_system') - { - require_once(e_HANDLER.'cron_class.php'); - } - else - { - require_once(e_PLUGIN.$class_name.'/e_cron.php'); - } - $class_name .= '_cron'; - $status = $this->cronExecuteMethod($class_name, $method_name) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR; - $mes->add("Running ".$this->cronName($taskName, $method_name)."", $status); - - } - - function cronSavePref() - { - // Store the USERID with the password. - // This way only the one password is needed, and the user login can be looked up in e_base/cron.php - - } - - function cronSave() - { - global $pref; - - $mes = e107::getMessage(); - $activeCount = 0; - - foreach ($_POST['cron'] as $key => $val) - { - if (!$val['active']) - { - $val['active'] = 0; - } - else - { - $activeCount++; - } - - $t['minute'] = implode(",", $_POST['tab'][$key]['minute']); - $t['hour'] = implode(",", $_POST['tab'][$key]['hour']); - $t['day'] = implode(",", $_POST['tab'][$key]['day']); - $t['month'] = implode(",", $_POST['tab'][$key]['month']); - $t['weekday'] = implode(",", $_POST['tab'][$key]['weekday']); - - $val['tab'] = implode(" ", $t); - $tabs .= $val['tab']."
"; - - list($class, $func) = explode("__", $key); - - $val['function'] = $func; - $val['class'] = $class; - $val['path'] = $class; - - $cron[$key] = $val; - } - - $pref['e_cron_pref'] = $cron; - - if (!vartrue($pref['e_cron_pwd']) || varset($_POST['generate_pwd'])) - { - $pwd = $this->setCronPwd(); - - $setpwd_message = "Use the following Cron Command:
".$_SERVER['DOCUMENT_ROOT'].e_HTTP."cron.php ".$pwd."
- This cron command is unique and will not be displayed again. Please copy and paste it into your webserver cron area to be run every minute (or 15 minutes) of every day."; - $mes->add($setpwd_message, E_MESSAGE_WARNING); - } - - // print_a($pref['e_cron_pref']); - - if (save_prefs()) - { - $mes->add(LAN_SETSAVED, E_MESSAGE_SUCCESS); - $mes->add($activeCount." Cron(s) Active", E_MESSAGE_SUCCESS); - } - else - { - $mes->add("There was a problem saving your settings.", E_MESSAGE_ERROR); - } - - } - - function setCronPwd() - { - //global $pref; - - $userMethods = e107::getUserSession(); - $newpwd = $userMethods->generateRandomString('*^*#.**^*'); - $newpwd = sha1($newpwd.time()); - //$pref['e_cron_pwd'] = $newpwd; - e107::getConfig()->set('e_cron_pwd', $newpwd)->save(false); - return true; - - } - - // -------------------------------------------------------------------------- - function cronRenderPrefs() - { - //global $frm,$ns; - $frm = e107::getForm(); - $text = "
-
- - - - - - - - - - - -
Cron Password - " - .$frm->password('cron_password', '', 100)." -
"; - $text .= $frm->admin_button('save_prefs', LAN_SAVE, 'update'); - - $text .= "
-
-
"; - - e107::getRender()->tablerender(LAN_PREFS, $text); - - } - - function cronLoad() //TODO Make a generic function to work with e_cron, e_sitelink, e_url etc. - - { - $pref = e107::getPref(); - - $core_cron = $this->coreCrons; // May need to check 'available' flag here - $new_cron = e107::getAddonConfig('e_cron'); - $this->e_cron = array_merge($core_cron, $new_cron); - return; - - } - - // ----------- Grab All e_cron parameters ----------------------------------- - - function cronRenderPage() - { - $pref = e107::getPref(); - $cronpref = $pref['e_cron_pref']; - $ns = e107::getRender(); - $frm = e107::getForm(); - $mes = e107::getMessage(); - - $e_cron = $this->e_cron; - - // ---------------------- List All Functions ----------------------------- - - $text = "
-
- - - - - - - - - - - - - - - - - - - - - - - - - "; - - foreach ($e_cron as $plug => $cfg) - { - foreach ($cfg as $class => $cron) - { - if (!isset($cron['available']) || $cron['available']) // Only display cron functions which are available - - { - $c = $plug.'__'.$cron['function']; // class and function. - $sep = array(); - - list($sep['minute'], $sep['hour'], $sep['day'], $sep['month'], $sep['weekday']) = explode(" ", $cronpref[$c]['tab']); - - foreach ($sep as $key => $value) - { - if ($value == "") - { - $sep[$key] = "*"; - } - } - - $minute = explode(",", $sep['minute']); - $hour = explode(",", $sep['hour']); - $day = explode(",", $sep['day']); - $month = explode(",", $sep['month']); - $weekday = explode(",", $sep['weekday']); - - $min_options = array( - "*" => LAN_CRON_11, - "0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58" => LAN_CRON_12, - "0,5,10,15,20,25,30,35,40,45,50,55" => LAN_CRON_13, - "0,10,20,30,40,50" => LAN_CRON_14, - "0,15,30,45" => LAN_CRON_10, - "0,30" => LAN_CRON_15 - ); - - $hour_options = array( - "*" => LAN_CRON_16, - "0,2,4,6,8,10,12,14,16,18,20,22" => LAN_CRON_17, - "0,3,6,9,12,15,18,21" => LAN_CRON_18, - "0,6,12,18" => LAN_CRON_19 - ); - - $text .= " - - - - - - - - - - - "; - } - } - } - $text .= " - - - - - -
" - .LAN_CRON_1XXX."" - .LAN_CRON_2."" - .LAN_CRON_3."" - .LAN_CRON_4."" - .LAN_CRON_5XXXX."" - .LAN_CRON_6."" - .LAN_CRON_7."" - .LAN_CRON_8."Run Now
" - .$cron['name']."" - .$cron['description']." - - - - - - - - - - - "; - $checked = ($cronpref[$c]['active'] == 1) ? "checked='checked'" : ""; - $text .= " - ".$frm->admin_button('execute['.$c.']', 'Run Now')."
-
"; - // $text .= ""; - $text .= $frm->admin_button('submit', LAN_SAVE, $action = 'update'); - $text .= $frm->checkbox_switch('generate_pwd', 1, '', 'Generate new cron command'); - $text .= "
-
-
"; - - $ns->tablerender(PAGE_NAME, $mes->render().$text); - } - - function cronOptions() - { - $e107 = e107::getInstance(); - - $var['main']['text'] = PAGE_NAME; - $var['main']['link'] = e_SELF; - - // $var['pref']['text'] = LAN_PREFS; - // $var['pref']['link'] = e_SELF."?pref"; - // $var['pref']['perm'] = "N"; - - $action = ($this->cronAction) ? $this->cronAction : 'main'; - - e107::getNav()->admin(PAGE_NAME, $action, $var); - } - - function cronExecuteMethod($class_name, $method_name, $return = 'boolean') - { - $mes = e107::getMessage(); - - if (class_exists($class_name)) - { - $obj = new $class_name; - if (method_exists($obj, $method_name)) - { - $mes->add("Executing config function ".$class_name." : ".$method_name."()", E_MESSAGE_DEBUG); - if ($return == 'boolean') - { - call_user_func(array($obj, $method_name)); - return TRUE; - } - else - { - return call_user_func(array($obj, $method_name)); - } - } - else - { - $mes->add("Config function ".$method_name."() NOT found.", E_MESSAGE_DEBUG); - } - } - return FALSE; - } -} - -function cron_adminmenu() -{ - global $cron; - $cron->cronOptions(); -} - */ - - -?> + array( + 'controller' => 'cron_admin_ui', + 'path' => null, + 'ui' => 'cron_admin_form_ui', + 'uipath' => null + ) + ); + + + protected $adminMenu = array( + 'main/list' => array('caption'=> LAN_MANAGE, 'perm' => '0'), + 'main/refresh' => array('caption'=> LAN_CRON_M_02, 'perm' => '0','url'=>'cron.php'), + // 'main/prefs' => array('caption'=> 'Settings', 'perm' => '0'), + // 'main/custom' => array('caption'=> 'Custom Page', 'perm' => '0') + ); + + protected $adminMenuAliases = array( + 'main/edit' => 'main/list' + ); + + protected $menuTitle = PAGE_NAME; + + protected $adminMenuIcon = 'e-cron-24'; + +} + +class cron_admin_ui extends e_admin_ui +{ + + protected $pluginTitle = PAGE_NAME; + protected $pluginName = 'core'; + protected $table = "cron"; + protected $pid = "cron_id"; + protected $listOrder = 'cron_category desc'; // Show 'upgrades' on first page. + protected $perPage = 10; + protected $batchDelete = TRUE; + + protected $fields = array( + 'checkboxes' => array('title'=> '', 'type' => null, 'width' =>'5%', 'forced'=> TRUE, 'thclass'=>'center', 'class'=>'center'), + 'cron_id' => array('title'=> LAN_ID, 'type' => 'number', 'width' =>'5%', 'forced'=> FALSE, 'nolist'=>TRUE), + 'cron_category' => array('title'=> LAN_CATEGORY, 'type' => 'method', 'data' => 'str', 'width'=>'auto','readonly' => 1, 'thclass' => '', 'batch' => TRUE, 'filter'=>TRUE), + 'cron_name' => array('title'=> LAN_NAME, 'type' => 'text', 'data'=>'str', 'width' => 'auto', 'readonly' => 1), + 'cron_description' => array('title'=> LAN_DESCRIPTION, 'type' => 'text', 'data'=>'str', 'width' => '35%', 'readonly' => 1), + 'cron_function' => array('title'=> LAN_CRON_2, 'type' => 'text', 'data'=>'str', 'width' => 'auto', 'thclass' => 'left first', 'readonly' => 1), + 'cron_tab' => array('title'=> LAN_CRON_3, 'type' => 'method', 'width' => 'auto'), // Display name + 'cron_lastrun' => array('title'=> LAN_CRON_4, 'type' => 'datestamp', 'data' => 'int', 'width' => 'auto', 'readonly' => 2), + 'cron_active' => array('title'=> LAN_ACTIVE, 'type' => 'boolean', 'data'=> 'int', 'thclass' => 'center', 'class'=>'center', 'filter' => true, 'batch' => true, 'width' => 'auto'), + 'options' => array('title'=> LAN_OPTIONS, 'type' => 'method', 'data'=> null, 'noedit'=>TRUE, 'forced'=>TRUE, 'width' => '10%', 'thclass' => 'center last', 'class' => 'right') + ); + + + // public function beforeCreate($new_data) + // { + + // } + private $curCrons = array(); + private $activeCrons = 0; + + function init() + { + $pref = e107::getPref(); + $sql = e107::getDb(); + + if(vartrue($_POST['cron_execute'])) + { + $executeID = key($_POST['cron_execute']); + $this->cronExecute($executeID); + } + + + if (!vartrue(e107::getPref('e_cron_pwd')) || varset($_POST['generate_pwd'])) + { + $pwd = $this->setCronPwd(); + } + + $sql->gen("SELECT cron_function,cron_active FROM #cron "); + while($row = $sql->fetch()) + { + $this->curCrons[] = $row['cron_function']; + if($row['cron_active']==1) + { + $this->activeCrons++; + } + } + + $this->lastRefresh(); + // Import Core and Plugin e_cron data + + $cronDefaults['_system'] = array( + 0 => array( + 'name' => LAN_CRON_01_1, + 'function' => 'sendEmail', + 'category' => 'mail', + 'description' => str_replace("[eml]",$pref['siteadminemail'],LAN_CRON_01_2) ."
". LAN_CRON_01_3 + ), + 1 => array( + 'name' => LAN_CRON_02_1, + 'category' => 'mail', + 'function' => 'procEmailQueue', + 'description' => LAN_CRON_02_2 + ), + 2 => array( + 'name' => LAN_CRON_03_1, + 'category' => 'mail', + 'function' => 'procEmailBounce', + 'description' => LAN_CRON_03_2 + // 'available' => vartrue($pref['mail_bounce_auto']) + ), + 3 => array( + 'name' => LAN_CRON_04_1, + 'category' => 'user', + 'function' => 'procBanRetrigger', + 'description' => LAN_CRON_04_2 ."
". LAN_CRON_04_3, + 'available' => e107::getPref('ban_retrigger') + ), + 4 => array( + 'name' => LAN_CRON_05_1, + 'category' => 'backup', + 'function' => 'dbBackup', + 'description' => LAN_CRON_05_2 .' '.e_SYSTEM.'backups/' + // 'available' => e107::getPref('ban_retrigger') + ), + 5 => array( + 'name' => LAN_CRON_06_1, + 'category' => 'user', + 'function' => 'procBanRetrigger', + 'description' => LAN_CRON_06_2 ."
". LAN_CRON_06_3, + // 'available' => e107::getPref('ban_retrigger') + ), + 6 => array( + 'name' => LAN_CRON_20_1, + 'category' => 'update', + 'function' => 'checkCoreUpdate', + 'description' => LAN_CRON_20_2 ."
". LAN_CRON_20_3, + // 'available' => e107::getPref('ban_retrigger') + ), + + ); + + if(is_dir(e_BASE.".git")) + { + $cronDefaults['_system'][7] = array( + 'name' => LAN_CRON_20_4, + 'category' => 'update', + 'function' => 'gitrepo', + 'description' => LAN_CRON_20_5."
".LAN_CRON_20_6."
".LAN_WARNING." ".LAN_CRON_20_8, + // 'available' => e107::getPref('ban_retrigger') + ); + + } + + + + + if(!vartrue($_GET['action']) || $_GET['action'] == 'refresh') + { + + $this->cronImport($cronDefaults); // import Core Crons (if missing) + $this->cronImport(e107::getAddonConfig('e_cron')); // Import plugin Crons + $this->cronImportLegacy(); // Import Legacy Cron Tab Settings + } + + $this->renderHelp(); + + } + + + + /** + * Import Cron Settings into Database. + */ + public function cronImport($new_cron = array()) + { + if(empty($new_cron)) + { + return null; + } + + $tp = e107::getParser(); + + foreach($new_cron as $class => $ecron) + { + foreach($ecron as $val) + { + $insert = array( + 'cron_id' => 0, + 'cron_name' => $val['name'], + 'cron_category' => $val['category'], + 'cron_description' => $tp->toDB($val['description']), + 'cron_function' => $class."::".$val['function'], + 'cron_tab' => varset($val['tab'], '* * * * *'), + 'cron_active' => varset($val['active'], '0'), + ); + + $this->cronInsert($insert); + } + } + } + + + + /** + * Import Legacy e_cron_pref settings. + */ + public function cronImportLegacy() + { + global $pref; + + $cronPref = e107::getPref('e_cron_pref'); + + + if(!is_array($cronPref)) + { + return; + } + + foreach($cronPref as $val) + { + $update = array( + 'cron_tab' => $val['tab'], + 'cron_active' => $val['active'], + 'cron_function' => $val['class']."::".$val['function'], + 'WHERE' => "cron_function = '".$val['class']."::".$val['function']."'" + ); + + $this->cronUpdate($update); + } + + e107::getConfig()->remove('e_cron_pref')->save(); + } + + + + + // Insert a Cron. + public function cronInsert($insert) + { + // print_a($insert); + // return; +// + $sql = e107::getDb(); + + if(in_array($insert['cron_function'],$this->curCrons)) + { + return; + } + + if(!$sql->insert('cron',$insert)) + { + e107::getMessage()->addDebug(LAN_CRON_6); + } + else + { + e107::getMessage()->add(LAN_CRON_8.": ".$insert['cron_function'], E_MESSAGE_INFO); + } + } + + + + /** + * Update cron timing - from legacy Pref. + */ + public function cronUpdate($insert) + { + // print_a($insert); + // return; + + $sql = e107::getDb(); + + $cron_function = $insert['cron_function']; + unset($insert['cron_function']); + + if($sql->update('cron',$insert)===FALSE) + { + e107::getMessage()->add(LAN_CRON_7, E_MESSAGE_ERROR); + } + else + { + e107::getMessage()->add(LAN_CRON_8.$cron_function, E_MESSAGE_INFO); + } + } + + + + + + // Process _POST before saving. + public function beforeUpdate($new_data, $old_data, $id) + { + $new_data['cron_tab'] = implode(" ", $new_data['tab']); + return $new_data; + } + + + function setCronPwd() + { + //global $pref; + $userMethods = e107::getUserSession(); + $newpwd = $userMethods->generateRandomString('*^*#.**^*'); + $newpwd = sha1($newpwd.time()); + + e107::getConfig()->set('e_cron_pwd', $newpwd)->save(false); + return true; + + } + + + + function lastRefresh() + { + $pref = e107::getPref(); + $mes = e107::getMessage(); + $frm = e107::getForm(); + + if(file_exists(e_CACHE.'cronLastLoad.php')) + { + $lastload = intval(@file_get_contents(e_CACHE.'cronLastLoad.php')); + } + else + { + $lastload = 0; + } + + $ago = (time() - $lastload); + + $active = ($ago < 1200) ? true : false; // longer than 20 minutes, so lets assume it's inactive. + $status = ($active) ? LAN_ENABLED : LAN_DISABLED; // "Enabled" : "Offline"; + + $mins = floor($ago / 60); + $secs = $ago % 60; + + $srch = array("[x]","[y]"); + $repl = array($mins,$secs); + + $lastRun = ($mins) ? str_replace($srch,$repl,LAN_CRON_9) : str_replace($srch,$repl,LAN_CRON_10); // FIX: check syntax + + $lastRefresh = ($ago < 10000) ? $lastRun : LAN_NEVER; + + $mes->addInfo(LAN_STATUS.": ".$status.""); + $mes->addInfo(LAN_CRON_11.": ".$this->activeCrons.""); + $mes->addInfo(LAN_CRON_12.": ".$lastRefresh."

"); + + + // extensions of exe, com, bat and cmd. + + $isWin = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; + $actualPerm = substr(decoct(fileperms(e_BASE."cron.php")),3); + + if($isWin) + { + $mes->addWarning(LAN_CRON_13); + } + if (!$isWin && $actualPerm != 755) // is_executable() is not reliable. + { + $mes->addWarning(LAN_CRON_14); + } + elseif (!$active) // show instructions + { + $setpwd_message = $frm->open("generate")."" + .LAN_CRON_15.":
".e_ROOT."cron.php token=".$pref['e_cron_pwd'].' >/dev/null 2>&1';
+				
+				$setpwd_message .= "
". LAN_CRON_16.""; + if(e_DOMAIN && file_exists("/usr/local/cpanel/version")) + { + $setpwd_message .= "
".LAN_CRON_60."
"; + + } + $setpwd_message .= "

".$frm->admin_button('generate_pwd', 1, 'delete', LAN_CRON_61 ,array('class'=>'btn btn-small')); + $setpwd_message .= $frm->close(); + + $mes->add($setpwd_message, E_MESSAGE_INFO); + } + + } + + function cronExecute($cron_id) + { + $sql = e107::getDb(); + if($sql->select("cron","cron_name,cron_function","cron_id = ".intval($cron_id))) + { + $row = $sql->fetch(); + $class_func = $row['cron_function']; + $cron_name = $row['cron_name']; + } + + if(!$class_func) + { + return; + } + + + list($class_name, $method_name) = explode("::", $class_func); + $mes = e107::getMessage(); + $taskName = $class_name; + + if ($class_name == '_system') + { + require_once(e_HANDLER.'cron_class.php'); + } + else + { + require_once(e_PLUGIN.$class_name.'/e_cron.php'); + } + $class_name .= '_cron'; + $status = $this->cronExecuteMethod($class_name, $method_name) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR; + $mes->add(LAN_CRON_RUNNING.":".$cron_name."", $status); + } + + + + function cronExecuteMethod($class_name, $method_name, $return = 'boolean') + { + $mes = e107::getMessage(); + + if (class_exists($class_name)) + { + $obj = new $class_name; + if (method_exists($obj, $method_name)) + { + $message = str_replace('[x]', $class_name." : ".$method_name, LAN_CRON_62);//Executing config function [b][x][/b] + $message = e107::getParser()->toHTML($message,true); + $mes->add($message, E_MESSAGE_DEBUG); + if ($return == 'boolean') + { + call_user_func(array($obj, $method_name)); + return TRUE; + } + else + { + return call_user_func(array($obj, $method_name)); + } + } + else + { + $message = str_replace('[x]', $method_name."()", LAN_CRON_63 );//Config function [b][x][/b] NOT found. + $message = e107::getParser()->toHTML($message,true); + $mes->add($message, E_MESSAGE_DEBUG); + } + } + return FALSE; + } + + function renderHelp() + { + return array('caption'=>LAN_HELP, 'text'=>e107::getParser()->toHTML(LAN_CRON_64, true)); + } + +} + +class cron_admin_form_ui extends e_admin_form_ui +{ + + var $min_options = array( + "*" => LAN_CRON_30, + "0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58" => LAN_CRON_31, + "0,5,10,15,20,25,30,35,40,45,50,55" => LAN_CRON_32, + "0,10,20,30,40,50" => LAN_CRON_33, + "0,15,30,45" => LAN_CRON_34, + "0,30" => LAN_CRON_35 + ); + + var $hour_options = array( + "*" => LAN_CRON_36, + "0,2,4,6,8,10,12,14,16,18,20,22" => LAN_CRON_37, + "0,3,6,9,12,15,18,21" => LAN_CRON_38, + "0,6,12,18" => LAN_CRON_39 + ); + + + var $cronCategories = array( + 'backup' => LAN_CRON_BACKUP, + 'content' => ADLAN_CL_3, + 'log' => LAN_CRON_LOGGING, + 'mail' => ADLAN_136, + 'notify' => ADLAN_149, + 'user' => LAN_USER, + 'plugin' => ADLAN_CL_7, + 'update' => LAN_UPDATE + ); + + /** + * Render cron_tab field + */ + function cron_tab($curVal,$mode) + { + if($mode == 'read') + { + $sep = array(); + list($min, $hour, $day, $month, $weekday) = explode(" ", $curVal); + $text = (isset($this->min_options[$min])) ? $this->min_options[$min] : LAN_CRON_50 ." ". $min; // Minute(s) + $text .= "
"; + $text .= (isset($this->hour_options[$hour])) ? $this->hour_options[$hour] : LAN_CRON_51 ." ". $hour; // Hour(s) + $text .= "
"; + $text .= ($day != '*') ? LAN_CRON_52 ." ". $day : LAN_CRON_40; // Day(s) + $text .= "
"; + $text .= ($month != '*') ? LAN_CRON_53 ." ". strftime("%B", mktime(00, 00, 00, $month, 1, 2000)) : LAN_CRON_41; // Month(s) + $text .= "
"; + $text .= ($weekday != '*') ? LAN_CRON_54 ." ". strftime("%A", mktime(00, 00, 00, 5, $weekday, 2000)) : LAN_CRON_42; // Weekday(s) + + + return "".ADMIN_INFO_ICON." +
".$text."
"; + + return $text; + } + + if($mode == 'write') + { + return $this->editTab($curVal); + } + + if($mode == 'filter') // Custom Filter List + { + return; + } + + if($mode == 'batch') + { + return; + } + } + + + function cron_category($curVal,$mode) + { + if($mode == 'read') + { + return isset($this->cronCategories[$curVal]) ? $this->cronCategories[$curVal] : ""; + } + + if($mode == 'write') + { + return isset($this->cronCategories[$curVal]) ? $this->cronCategories[$curVal] : ""; + } + + if($mode == 'filter') + { + return $this->cronCategories; + } + if($mode == 'batch') + { + return; + } + } + + // Override the default Options field. + function options($parms, $value, $id, $attributes) + { + $att = $attributes; + if($attributes['mode'] == 'read') + { + $func = $this->getController()->getFieldVar('cron_function'); + // + if(substr($func,0,7) === '_system') + { + $att['readParms'] = array('disabled'=>'disabled'); + } + + $text = "
"; + $text .= $this->renderValue('options',$value,$att,$id); + $text .= $this->submit_image('cron_execute['.$id.']', 1, 'execute', LAN_RUN); + $text .= "
"; + + + return $text; + } + } + + + function editTab($curVal) + { + $sep = array(); + list($sep['minute'], $sep['hour'], $sep['day'], $sep['month'], $sep['weekday']) = explode(" ", $curVal); + + foreach ($sep as $key => $value) + { + if ($value == "") + { + $sep[$key] = "*"; + } + } + + $minute = explode(",", $sep['minute']); + $hour = explode(",", $sep['hour']); + $day = explode(",", $sep['day']); + $month = explode(",", $sep['month']); + $weekday = explode(",", $sep['weekday']); + + + + $text = " + + + + + + + + + "; + + return $text; + + } + + + + +} + +new cron_admin(); + + + +$e_sub_cat = 'cron'; + +require_once('auth.php'); + +e107::getAdminUI()->runPage(); +$frm = e107::getForm(); +// $cron = new cron(); + +require_once(e_ADMIN.'footer.php'); +exit; +/* +class cron +{ + protected $coreCrons = array(); + protected $cronAction; + protected $e_cron = array(); + + public function __construct() + { + $pref = e107::getPref(); + $mes = e107::getMessage(); + $this->cronAction = e_QUERY; + + // The 'available' flag only gives the option to configure the cron if the underlying feature is enabled + $this->coreCrons['_system'] = array( + 0 => array('name' => 'Test Email', 'function' => 'sendEmail', 'description' => 'Send a test email to '.$pref['siteadminemail'].'
Recommended to test the scheduling system.'), + 1 => array('name' => 'Mail Queue', 'function' => 'procEmailQueue', 'description' => 'Process mail queue'), + 2 => array('name' => 'Mail Bounce Check', 'function' => 'procEmailBounce', 'description' => 'Check for bounced emails', 'available' => vartrue($pref['mail_bounce_auto'])), + // 1 => array('name'=>'User Purge', 'function' => 'userPurge', 'description'=>'Purge Unactivated Users'), + // 2 => array('name'=>'User UnActivated', 'function' => 'userUnactivated', 'description'=>'Resend activation email to unactivated users.'), + // 3 => array('name'=>'News Sticky', 'function' => 'newsPurge', 'description'=>'Remove Sticky News Items') + ); + + if (!vartrue($pref['e_cron_pwd'])) + { + $pwd = $this->setCronPwd(); + } + + if (isset($_POST['submit'])) + { + $this->cronSave(); + } + + $this->lastRefresh(); + $this->cronLoad(); + + if (isset($_POST['save_prefs'])) + { + $this->cronSavePrefs(); + } + + if (isset($_POST['execute'])) + { + + $class_func = key($_POST['execute']); + $this->cronExecute($class_func); + } + + // Set Core Cron Options. + + // These core functions need to be put into e_BASE/cron.php ie. news_purge() + + if ($this->cronAction == "" || $this->cronAction == "main") + { + $this->cronRenderPage(); + } + + if ($this->cronAction == "pref") + { + $this->cronRenderPrefs(); + } + } + + function lastRefresh() + { + $pref = e107::getPref(); + e107::getCache()->CachePageMD5 = '_'; + $lastload = e107::getCache()->retrieve('cronLastLoad', FALSE, TRUE, TRUE); + $mes = e107::getMessage(); + $ago = (time() - $lastload); + + $active = ($ago < 901) ? TRUE : FALSE; + $status = ($active) ? LAN_ENABLED : LAN_DISABLED; // "Enabled" : "Offline"; + + $mins = floor($ago / 60); + $secs = $ago % 60; + + $lastRun = ($mins) ? $mins." minutes and ".$secs." seconds ago." : $secs." seconds ago."; + + $lastRefresh = ($ago < 10000) ? $lastRun : 'Never'; + + $mes->add("Status: ".$status."", E_MESSAGE_INFO); + + // print_a($pref['e_cron_pref']); + + if ($pref['e_cron_pref']) // grab cron + + { + foreach ($pref['e_cron_pref'] as $func => $cron) + { + if ($cron['active'] == 1) + { + $list[$func] = $cron; + } + } + } + + $mes->add("Active Crons: ".count($list)."", E_MESSAGE_INFO); + $mes->add("Last cron refresh: ".$lastRefresh, E_MESSAGE_INFO); + + //FIXME: for Windows, the is_executable() function only checks the file + // extensions of exe, com, bat and cmd. + + + $actualPerms = fileperms(e_BASE."cron.php"); + + if (!is_executable(realpath(e_BASE."cron.php"))) + { + $mes->add("Please CHMOD /cron.php to 755 ", E_MESSAGE_WARNING); + } + //elseif (!$active) - always show instructions + { + $setpwd_message = "Use the following Cron Command: ".$_SERVER['DOCUMENT_ROOT'].e_HTTP."cron.php ".$pref['e_cron_pwd']."
+ Using your server control panel (eg. cPanel,Plesk etc.) please create a crontab to run this command on your server every minute."; + $mes->add($setpwd_message, E_MESSAGE_INFO); + } + + } + + function cronName($classname, $method) + { + $tp = e107::getParser(); + + foreach ($this->e_cron as $class => $val) + { + + if ($class == $classname) + { + foreach ($val as $func) + { + if ($func['function'] == $method) + { + return $tp->toHTML($func['name']); + } + } + } + } + } + + function cronExecute($class_func) + { + //TO/ DO L/ANs + list($class_name, $method_name) = explode("__", $class_func); + $mes = e107::getMessage(); + + $taskName = $class_name; + if ($class_name == '_system') + { + require_once(e_HANDLER.'cron_class.php'); + } + else + { + require_once(e_PLUGIN.$class_name.'/e_cron.php'); + } + $class_name .= '_cron'; + $status = $this->cronExecuteMethod($class_name, $method_name) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR; + $mes->add("Running ".$this->cronName($taskName, $method_name)."", $status); + + } + + function cronSavePref() + { + // Store the USERID with the password. + // This way only the one password is needed, and the user login can be looked up in e_base/cron.php + + } + + function cronSave() + { + global $pref; + + $mes = e107::getMessage(); + $activeCount = 0; + + foreach ($_POST['cron'] as $key => $val) + { + if (!$val['active']) + { + $val['active'] = 0; + } + else + { + $activeCount++; + } + + $t['minute'] = implode(",", $_POST['tab'][$key]['minute']); + $t['hour'] = implode(",", $_POST['tab'][$key]['hour']); + $t['day'] = implode(",", $_POST['tab'][$key]['day']); + $t['month'] = implode(",", $_POST['tab'][$key]['month']); + $t['weekday'] = implode(",", $_POST['tab'][$key]['weekday']); + + $val['tab'] = implode(" ", $t); + $tabs .= $val['tab']."
"; + + list($class, $func) = explode("__", $key); + + $val['function'] = $func; + $val['class'] = $class; + $val['path'] = $class; + + $cron[$key] = $val; + } + + $pref['e_cron_pref'] = $cron; + + if (!vartrue($pref['e_cron_pwd']) || varset($_POST['generate_pwd'])) + { + $pwd = $this->setCronPwd(); + + $setpwd_message = "Use the following Cron Command:
".$_SERVER['DOCUMENT_ROOT'].e_HTTP."cron.php ".$pwd."
+ This cron command is unique and will not be displayed again. Please copy and paste it into your webserver cron area to be run every minute (or 15 minutes) of every day."; + $mes->add($setpwd_message, E_MESSAGE_WARNING); + } + + // print_a($pref['e_cron_pref']); + + if (save_prefs()) + { + $mes->add(LAN_SETSAVED, E_MESSAGE_SUCCESS); + $mes->add($activeCount." Cron(s) Active", E_MESSAGE_SUCCESS); + } + else + { + $mes->add("There was a problem saving your settings.", E_MESSAGE_ERROR); + } + + } + + function setCronPwd() + { + //global $pref; + + $userMethods = e107::getUserSession(); + $newpwd = $userMethods->generateRandomString('*^*#.**^*'); + $newpwd = sha1($newpwd.time()); + //$pref['e_cron_pwd'] = $newpwd; + e107::getConfig()->set('e_cron_pwd', $newpwd)->save(false); + return true; + + } + + // -------------------------------------------------------------------------- + function cronRenderPrefs() + { + //global $frm,$ns; + $frm = e107::getForm(); + $text = "
+
+ + + + + + + + + + + +
Cron Password + " + .$frm->password('cron_password', '', 100)." +
"; + $text .= $frm->admin_button('save_prefs', LAN_SAVE, 'update'); + + $text .= "
+
+
"; + + e107::getRender()->tablerender(LAN_PREFS, $text); + + } + + function cronLoad() //TODO Make a generic function to work with e_cron, e_sitelink, e_url etc. + + { + $pref = e107::getPref(); + + $core_cron = $this->coreCrons; // May need to check 'available' flag here + $new_cron = e107::getAddonConfig('e_cron'); + $this->e_cron = array_merge($core_cron, $new_cron); + return; + + } + + // ----------- Grab All e_cron parameters ----------------------------------- + + function cronRenderPage() + { + $pref = e107::getPref(); + $cronpref = $pref['e_cron_pref']; + $ns = e107::getRender(); + $frm = e107::getForm(); + $mes = e107::getMessage(); + + $e_cron = $this->e_cron; + + // ---------------------- List All Functions ----------------------------- + + $text = "
+
+ + + + + + + + + + + + + + + + + + + + + + + + + "; + + foreach ($e_cron as $plug => $cfg) + { + foreach ($cfg as $class => $cron) + { + if (!isset($cron['available']) || $cron['available']) // Only display cron functions which are available + + { + $c = $plug.'__'.$cron['function']; // class and function. + $sep = array(); + + list($sep['minute'], $sep['hour'], $sep['day'], $sep['month'], $sep['weekday']) = explode(" ", $cronpref[$c]['tab']); + + foreach ($sep as $key => $value) + { + if ($value == "") + { + $sep[$key] = "*"; + } + } + + $minute = explode(",", $sep['minute']); + $hour = explode(",", $sep['hour']); + $day = explode(",", $sep['day']); + $month = explode(",", $sep['month']); + $weekday = explode(",", $sep['weekday']); + + $min_options = array( + "*" => LAN_CRON_11, + "0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58" => LAN_CRON_12, + "0,5,10,15,20,25,30,35,40,45,50,55" => LAN_CRON_13, + "0,10,20,30,40,50" => LAN_CRON_14, + "0,15,30,45" => LAN_CRON_10, + "0,30" => LAN_CRON_15 + ); + + $hour_options = array( + "*" => LAN_CRON_16, + "0,2,4,6,8,10,12,14,16,18,20,22" => LAN_CRON_17, + "0,3,6,9,12,15,18,21" => LAN_CRON_18, + "0,6,12,18" => LAN_CRON_19 + ); + + $text .= " + + + + + + + + + + + "; + } + } + } + $text .= " + + + + + +
" + .LAN_CRON_1XXX."" + .LAN_CRON_2."" + .LAN_CRON_3."" + .LAN_CRON_4."" + .LAN_CRON_5XXXX."" + .LAN_CRON_6."" + .LAN_CRON_7."" + .LAN_CRON_8."Run Now
" + .$cron['name']."" + .$cron['description']." + + + + + + + + + + + "; + $checked = ($cronpref[$c]['active'] == 1) ? "checked='checked'" : ""; + $text .= " + ".$frm->admin_button('execute['.$c.']', 'Run Now')."
+
"; + // $text .= ""; + $text .= $frm->admin_button('submit', LAN_SAVE, $action = 'update'); + $text .= $frm->checkbox_switch('generate_pwd', 1, '', 'Generate new cron command'); + $text .= "
+
+
"; + + $ns->tablerender(PAGE_NAME, $mes->render().$text); + } + + function cronOptions() + { + $e107 = e107::getInstance(); + + $var['main']['text'] = PAGE_NAME; + $var['main']['link'] = e_SELF; + + // $var['pref']['text'] = LAN_PREFS; + // $var['pref']['link'] = e_SELF."?pref"; + // $var['pref']['perm'] = "N"; + + $action = ($this->cronAction) ? $this->cronAction : 'main'; + + e107::getNav()->admin(PAGE_NAME, $action, $var); + } + + function cronExecuteMethod($class_name, $method_name, $return = 'boolean') + { + $mes = e107::getMessage(); + + if (class_exists($class_name)) + { + $obj = new $class_name; + if (method_exists($obj, $method_name)) + { + $mes->add("Executing config function ".$class_name." : ".$method_name."()", E_MESSAGE_DEBUG); + if ($return == 'boolean') + { + call_user_func(array($obj, $method_name)); + return TRUE; + } + else + { + return call_user_func(array($obj, $method_name)); + } + } + else + { + $mes->add("Config function ".$method_name."() NOT found.", E_MESSAGE_DEBUG); + } + } + return FALSE; + } +} + +function cron_adminmenu() +{ + global $cron; + $cron->cronOptions(); +} + */ + + +?> diff --git a/e107_admin/emoticon.php b/e107_admin/emoticon.php index 31d8cebbd..e43bc8e4e 100644 --- a/e107_admin/emoticon.php +++ b/e107_admin/emoticon.php @@ -1,705 +1,705 @@ -clearPrefCache('emote'); - -require_once("auth.php"); - -$mes = e107::getMessage(); - -if(!$sql->db_Count("core", "(*)", "WHERE e107_name = 'emote_default' AND e107_value !='' ")) -{ // Set up the default emotes -// $tmp = 'a:28:{s:9:"alien!png";s:6:"!alien";s:10:"amazed!png";s:7:"!amazed";s:9:"angry!png";s:11:"!grr !angry";s:12:"biglaugh!png";s:4:"!lol";s:11:"cheesey!png";s:10:":D :oD :-D";s:12:"confused!png";s:10:":? :o? :-?";s:7:"cry!png";s:19:"&| &-| &o| :(( !cry";s:8:"dead!png";s:21:"x) xo) x-) x( xo( x-(";s:9:"dodge!png";s:6:"!dodge";s:9:"frown!png";s:10:":( :o( :-(";s:7:"gah!png";s:10:":@ :o@ :o@";s:8:"grin!png";s:10:":D :oD :-D";s:9:"heart!png";s:6:"!heart";s:8:"idea!png";s:10:":! :o! :-!";s:7:"ill!png";s:4:"!ill";s:7:"mad!png";s:13:"~:( ~:o( ~:-(";s:12:"mistrust!png";s:9:"!mistrust";s:11:"neutral!png";s:10:":| :o| :-|";s:12:"question!png";s:2:"?!";s:12:"rolleyes!png";s:10:"B) Bo) B-)";s:7:"sad!png";s:4:"!sad";s:10:"shades!png";s:10:"8) 8o) 8-)";s:7:"shy!png";s:4:"!shy";s:9:"smile!png";s:10:":) :o) :-)";s:11:"special!png";s:3:"%-6";s:12:"suprised!png";s:10:":O :oO :-O";s:10:"tongue!png";s:21:":p :op :-p :P :oP :-P";s:8:"wink!png";s:10:";) ;o) ;-)";}'; -// $insert = array("e107_name"=>"emote_default", "e107_value"=>$tmp); -// $sql->db_Replace("core", $insert); -} - - -// Change the active emote pack -if (isset($_POST['active'])) -{ - if ($pref['smiley_activate'] != $_POST['smiley_activate']) - { - $pref['smiley_activate'] = $_POST['smiley_activate']; - e107::getLog()->add($pref['smiley_activate'] ? 'EMOTE_02' : 'EMOTE_03', $pref['emotepack'], E_LOG_INFORMATIVE, ''); - save_prefs(); - $update = true; - - } - else - { - $mes->addInfo(LAN_NO_CHANGE); - } - -} - -e107::getRender()->tablerender($caption, $mes->render() . $text); - -/* get packs */ -require_once(e_HANDLER."file_class.php"); -$fl = e107::getFile(); -$emote = new emotec; -$one_pack = FALSE; -$filtered = e107::getParser()->filter($_POST); - -// Check for pack-related buttons pressed -foreach($filtered as $key => $value) -{ - if(strstr($key, "subPack_")) - { - $subpack = str_replace("subPack_", "", $key); - $emote->emoteConf($subpack); - break; - } - - if(strstr($key, "XMLPack_")) - { - $subpack = str_replace("XMLPack_", "", $key); - $emote->emoteXML($subpack); - break; - } - - if(strstr($key, "defPack_")) - { - $pref['emotepack'] = str_replace("defPack_", "", $key); - if(save_prefs()) - { - $mes->addSuccess(LAN_UPDATED); - } - else - { - $mes->addInfo(LAN_NO_CHANGE); - } - e107::getLog()->add('EMOTE_01', $pref['emotepack'], E_LOG_INFORMATIVE, ''); - break; - } - - if(strstr($key, "scanPack_")) - { - $one_pack = str_replace("scanPack_", "", $key); - break; - } -} - -$ns->tablerender($caption, $mes->render() . $text); - - -$check = TRUE; -//$check = $emote -> installCheck(); -$check = $emote->installCheck($one_pack); -if($check!==FALSE) -{ - $emote -> listPacks(); -} - - - -class emotec -{ - var $packArray; // Stores an array of all available emote packs (as subdirectory names) - - function emotec() - { - /* constructor */ - $fl = e107::getFile(); - $this -> packArray = $fl->get_dirs(e_IMAGE."emotes"); - - if(isset($_POST['sub_conf'])) - { // Update stored pack configuration - $this -> saveConf(); - } - } - - - // List available emote packs - function listPacks() - { - $pref = e107::getPref(); - $frm = e107::getForm(); - $fl = e107::getFile(); - $ns = e107::getRender(); - $mes = e107::getMessage(); - - $text = " - - - -
-
-
-
- ".EMOLAN_1." - - - - - - - - - - - -
- ".EMOLAN_4.": - -
- ".$frm->checkbox('smiley_activate', 1, varset($pref['smiley_activate'],0))." -
-
-
- ".$frm->admin_button('active','active','update',LAN_UPDATE)." -
-
- -
- "; - - $text .= " -
-
-
- ".EMOLAN_13." - - - - - - - - - - - - - - - - - "; - - $reject = '~^emoteconf|\.html$|\.php$|\.txt$'; // Files to exclude - foreach($this -> packArray as $pack) - { - $can_scan = FALSE; - $emoteArray = $fl -> get_files(e_IMAGE.'emotes/'.$pack, $reject); - - $text .= " - - - - - - - "; - } - - $text .= " - -
".LAN_NAME."".EMOLAN_3."".LAN_STATUS."".LAN_OPTIONS."
{$pack} - "; - - foreach($emoteArray as $emote) - { - if (strstr($emote['fname'], ".pak") - || strstr($emote['fname'], ".xml") - || strstr($emote['fname'], "phpBB")) - { - $can_scan = TRUE; // Allow re-scan of config files - } - //elseif (!strstr($emote['fname'], ".txt") && !strstr($emote['fname'], ".bak") && !strstr($emote['fname'], ".html") && !strstr($emote['fname'], ".php") ) - else - { // Emote file found (might get other non-image files, but shouldn't) - $text .= " "; - } - } - - $text .= " - ".($pref['emotepack'] == $pack ? "".LAN_ACTIVE."" : "").""; - - - - - $text .= $frm->admin_button('subPack_'.$pack,'edit','default',LAN_CONFIGURE); - - if ($can_scan && ($pack != 'default')) - { - // $text .= ""; - $text .= $frm->admin_button('scanPack_'.$pack,'active','default',EMOLAN_26); - } - - $text .= $frm->admin_button('XMLPack_'.$pack,'submit','default',EMOLAN_28); - $text .= " -
-
-
-
-
- - "; - - $ns->tablerender(EMOLAN_PAGE_TITLE, $mes->render().$text); - } - - - // Configure an individual emote pack - function emoteConf($packID) - { - global $e107, $sysprefs; - $frm = e107::getForm(); - $tp = e107::getParser(); - $fl = e107::getFile(); - $ns = e107::getRender(); - - $packID = $tp->filter($packID); - $corea = "emote_".$packID; - - $emotecode = $sysprefs -> getArray($corea); - $reject = '~^emoteconf|\.html$|\.php$|\.txt$|\.pak$|\.xml|\.phpBB'; // Files to exclude - $emoteArray = $fl -> get_files(e_IMAGE."emotes/".$packID, $reject); - - $eArray = array(); - foreach($emoteArray as $value) - { - $eArray[] = array('path' => $value['path'], 'fname' => $value['fname']); - } - - //XXX Not sure if we need to know rhe number of files found - count($eArray) -
Total ".count($eArray)." files found
- $text = " -
-
- ".LAN_EDIT." -
".$tp->lanVars(EMOLAN_31, count($eArray))."
- - - - - - - - - - - - - - - "; - - foreach($eArray as $emote) - { - $ename = $emote['fname']; - $evalue = str_replace(".", "!", $ename); - $file_back = ''; - $text_back = ''; - - if (!isset($emotecode[$evalue])) - { - $file_back = '  '.EMOLAN_37.''; - } - elseif (!$emotecode[$evalue]) - { - $text_back = '  '.EMOLAN_38.''; - } - $text .= " - - - - - - "; - } - - $text .= " - -
".EMOLAN_5."".LAN_NAME."".EMOLAN_6." ( ".EMOLAN_7." )
".$ename."{$file_back} - {$text_back} -
-
- "; - - - $text .= $frm->admin_button('sub_conf', 'no-value', 'update', LAN_SAVE); - $text .= $frm->admin_button('cancel','no-value', 'cancel' ,LAN_CANCEL); - - $text .= " -
-
-
"; - - $ns->tablerender(EMOLAN_PAGE_TITLE.SEP.LAN_EDIT.": '".$packID."'", $text); - } - - - // Generate an XML file - packname.xml in root emoticon directory - function emoteXML($packID, $strip_xtn = TRUE) - { - global $sysprefs; - $mes = e107::getMessage(); - $fl = e107::getFile(); - $tp = e107::getParser(); - - $packID = $tp->filter($packID); - - $fname = e_IMAGE."emotes/".$packID."/emoticons.xml"; - $backname = e_IMAGE."emotes/".$packID."/emoticons.bak"; - - $corea = "emote_".$packID; - $emotecode = $sysprefs -> getArray($corea); - - $reject = '~^emoteconf|\.html$|\.php$|\.txt$|\.pak$|\.xml|\.phpBB'; // Files to exclude - $emoteArray = $fl -> get_files(e_IMAGE."emotes/".$packID, $reject); - - $eArray = array(); - foreach($emoteArray as $value) - { - $eArray[] = $value['fname']; - } - - $f_string = "\n\n\n\n"; - - foreach($eArray as $emote) - { - // Optionally strip file extension - $evalue = str_replace(".", "!", $emote); - if ($strip_xtn) $ename = substr($emote,0,strrpos($emote,'.')); - $f_string .= "\n"; - foreach (explode(' ',$tp -> toForm($emotecode[$evalue])) as $v) - { - if (trim($v)) $f_string .= "\t{$v}\n"; - } - $f_string .= "\n"; - } - - $f_string .= "\n\n"; - - if (is_file($backname)) unlink($backname); // Delete any old backup - - if (is_file($fname)) rename($fname,$backname); - - if (file_put_contents($fname,$f_string) === FALSE) - { - $mes->addWarning(''.EMOLAN_30.':'.str_replace(e_IMAGE, e_IMAGE_ABS, $fname)); - } - else - { - $mes->addSuccess(''.EMOLAN_29.':'.str_replace(e_IMAGE, e_IMAGE_ABS, $fname)); - } - } - - - // Save configuration for an emote pack that's been edited - function saveConf() - { - $sql = e107::getDb(); - $tp = e107::getParser(); - - - $packID = $_POST['packID']; - unset($_POST['sub_conf'], $_POST['packID']); - $encoded_emotes = $tp->toDB($_POST); - // $tmp = addslashes(serialize($encoded_emotes)); - $tmp = e107::getArrayStorage()->WriteArray($encoded_emotes); - - if ($sql->db_Select("core", "*", "e107_name='emote_".$packID."'")) - { - e107::getMessage()->addAuto($sql->update("core", "`e107_value`='{$tmp}' WHERE `e107_name`='emote_".$packID."' "), 'update', LAN_SETSAVED, false, false); - } - else - { - e107::getMessage()->addAuto($sql->insert("core", "'emote_".$packID."', '$tmp' "), 'insert', LAN_SETSAVED, false, false); - } - } - - - // Identify currently selected emote pack. Read in any new ones - // Return false to disable listing of packs - function installCheck($do_one = FALSE) - { - global $e107; - $sql = e107::getDb(); - $fl = e107::getFile(); - $ns = e107::getRender(); - $mes = e107::getMessage(); - - // Pick up a list of emote packs from the database - $pack_local = array(); - if ($sql->select("core","*","`e107_name` LIKE 'emote_%'")) - { - while ($row = $sql->fetch()) - { - $pack_local[substr($row['e107_name'],6)] = TRUE; - } - } - - foreach($this -> packArray as $value) - { - if(strpos($value,' ')!==FALSE) - { // Highlight any directory names containing spaces - not allowed - $msg = " - ".EMOLAN_17." ".EMOLAN_18.": -
".LAN_NAME.": {$value}
-
".EMOLAN_20.": ".e_IMAGE_ABS."emotes/
- "; - $mes->addError($msg); - $ns->tablerender(EMOLAN_PAGE_TITLE.' - '.EMOLAN_21, $mes->render()); - return FALSE; - } - - if (array_key_exists($value,$pack_local)) - { - unset($pack_local[$value]); - } - - if (($do_one == $value) || !$do_one && (!$sql -> db_Select("core", "*", "e107_name='emote_".$value."' "))) - { // Pack info not in DB, or to be re-scanned - $no_error = TRUE; - $File_type = EMOLAN_32.":"; - // Array of all files in the directory of the selected emote pack - $fileArray = $fl -> get_files(e_IMAGE."emotes/".$value); // We actually want all the files in the directory - $confFile = ''; - foreach($fileArray as $k => $file) - { - if(strstr($file['fname'], ".xml")) - { - $confFile = array('file' => $file['fname'], 'type' => "xml"); - } - else if(strstr($file['fname'], ".pak")) - { - $confFile = array('file' => $file['fname'], 'type' => "pak"); - } - else if(strstr($file['fname'], ".php")) - { - $confFile = array('file' => $file['fname'], 'type' => "php"); - } - if ($confFile) - { - unset($fileArray[$k]); - break; - } - } - - /* .pak file */ - if($confFile['type'] == "pak") - { - $filename = e_IMAGE."emotes/".$value."/".$confFile['file']; - $pakconf = file ($filename); - $contentArray = array(); - foreach($pakconf as $line) - { - if(trim($line) && strstr($line, "=+") && !strstr($line, ".txt") && !strstr($line, ".html") && !strstr($line, "cvs")) $contentArray[] = $line; - } - $confArray = array(); - foreach($contentArray as $pakline) - { - $tmp = explode("=+:", $pakline); - $confIC = str_replace(".", "!", $tmp[0]); - $confArray[$confIC] = trim($tmp[2]); - } - // $tmp = addslashes(serialize($confArray)); - $tmp = e107::serialize($confArray); - $File_type = EMOLAN_22.":"; - } - /* end */ - - /* .xml file */ - if($confFile['type'] == "xml") - { - $filename = e_IMAGE."emotes/".$value."/".$confFile['file']; - $contents = file_get_contents($filename); - $confArray = array(); - $xml_type = 0; - - if ((strpos($contents, "") !== FALSE) && (strpos($contents, "") !== FALSE)) - { // xep-0038 format - /* Example: - - :-) - :) - happy.png - choir.wav - */ - preg_match_all("#\(.*?)\<\/icon\>#si", $contents, $match); - - $xml_type = 1; - // $match[0] - complete emoticon entry - // $match[1] - match string and object specification - $item_index = 1; - } - elseif (strpos($contents, ""; - preg_match_all("#\(.*?)\<\/emoticon\>#si", $contents, $match); - - $xml_type = 2; - // $match[0] - complete emoticon entry - // $match[1] - filename (may or may not not have file extension/suffix) - // $match[2] - match string(s) representing emote - $item_index = 2; - } - - if ($xml_type) - { - for($a=0; $a < count($match[0]); $a++) - { - $e_file = ''; - switch ($xml_type) - { - case 1 : // xep-0038 - // Pull out a file name (only support first image type) - its in $fmatch[1] - if (preg_match("#\(.*?)\<\/object\>#si",$match[1][$a],$fmatch)) - { - $e_file = $fmatch[1]; -// echo "xep-0038 file: ".$e_file."
"; - // Pull out all match strings - need to pick out any language definitions for posterity - // but currently accept all language strings - preg_match_all("#\|\s*?xml\:lang\=\"(.*?)\"\>)(.*?)\<\/text\>#si", $match[1][$a], $match2); - // $match2[1] is the languages - // $match2[2] is the match strings - $codet = implode(" ",$match2[2]); - } - break; - case 2 : - $e_file = $match[1][$a]; - // Now pull out all the 'match' strings - preg_match_all("#\(.*?)\<\/string\>#si", $match[2][$a], $match2); - $codet = implode(" ",$match2[1]); - break; - } - // $e_file has the emote file name - // $match2 has an array of substitution strings - - - $file = ''; - foreach($fileArray as $emote) - { // Check that the file exists - if (strpos($e_file,".") === FALSE) - { // File extension not specified - accept any file extension for match - if(strpos($emote['fname'], $e_file.".") === 0) - { - $file = str_replace(".", "!", $emote['fname']); - break; - } - } - else - { // File extension specified - do simple match - if($emote['fname'] == $e_file) - { - $file = str_replace(".", "!", $emote['fname']); - break; - } - } - } - // Only add if the file exists. OK if no definition - might want to be added - if ($file) - { - $confArray[$file] = $codet; - } - } - } - else - { - //echo "Unsupported XML File Format

"; - $mes->addWarning(EMOLAN_33); - $no_error = FALSE; - } - - - // Save pack info in the database - // $tmp = addslashes(serialize($confArray)); - $tmp = e107::getArrayStorage()->WriteArray($confArray); - $File_type = EMOLAN_23.":"; - } - - if($confFile['type'] == "php") - { - include_once(e_IMAGE."emotes/".$value."/".$confFile['file']); - $File_type = EMOLAN_24.":"; - $tmp = $_emoteconf; // Use consistent name - } - - if ($no_error) - { - if ($do_one) - { // Assume existing pack - $sql->update("core", "`e107_value`='{$tmp}' WHERE `e107_name`='emote_".$value."'"); - } - else - { // Assume new pack - $sql->insert("core", "'emote_".$value."', '{$tmp}' "); - } - $mes->addInfo("{$File_type} '{$value}'"); - } - else - { // Error occurred - $mes->addError(EMOLAN_27.": '{$value}'"); - } - } - } - - - - if (count($pack_local)) - { - foreach ($pack_local as $p => $d) - { - if($p == '0') - { - $p = ''; - } - - if($sql->delete("core","`e107_name` = 'emote_{$p}'")) - { - $mes->addInfo(EMOLAN_34.":".$p.EMOLAN_35); - } - } - } - - return TRUE; - } - -} -require_once("footer.php"); -/** - * Handle page DOM within the page header - * - * @return string JS source - */ -function headerjs() -{ -/* require_once(e_HANDLER.'js_helper.php'); - - $ret = " - - - "; - - return $ret;*/ -} +clearPrefCache('emote'); + +require_once("auth.php"); + +$mes = e107::getMessage(); + +if(!$sql->db_Count("core", "(*)", "WHERE e107_name = 'emote_default' AND e107_value !='' ")) +{ // Set up the default emotes +// $tmp = 'a:28:{s:9:"alien!png";s:6:"!alien";s:10:"amazed!png";s:7:"!amazed";s:9:"angry!png";s:11:"!grr !angry";s:12:"biglaugh!png";s:4:"!lol";s:11:"cheesey!png";s:10:":D :oD :-D";s:12:"confused!png";s:10:":? :o? :-?";s:7:"cry!png";s:19:"&| &-| &o| :(( !cry";s:8:"dead!png";s:21:"x) xo) x-) x( xo( x-(";s:9:"dodge!png";s:6:"!dodge";s:9:"frown!png";s:10:":( :o( :-(";s:7:"gah!png";s:10:":@ :o@ :o@";s:8:"grin!png";s:10:":D :oD :-D";s:9:"heart!png";s:6:"!heart";s:8:"idea!png";s:10:":! :o! :-!";s:7:"ill!png";s:4:"!ill";s:7:"mad!png";s:13:"~:( ~:o( ~:-(";s:12:"mistrust!png";s:9:"!mistrust";s:11:"neutral!png";s:10:":| :o| :-|";s:12:"question!png";s:2:"?!";s:12:"rolleyes!png";s:10:"B) Bo) B-)";s:7:"sad!png";s:4:"!sad";s:10:"shades!png";s:10:"8) 8o) 8-)";s:7:"shy!png";s:4:"!shy";s:9:"smile!png";s:10:":) :o) :-)";s:11:"special!png";s:3:"%-6";s:12:"suprised!png";s:10:":O :oO :-O";s:10:"tongue!png";s:21:":p :op :-p :P :oP :-P";s:8:"wink!png";s:10:";) ;o) ;-)";}'; +// $insert = array("e107_name"=>"emote_default", "e107_value"=>$tmp); +// $sql->db_Replace("core", $insert); +} + + +// Change the active emote pack +if (isset($_POST['active'])) +{ + if ($pref['smiley_activate'] != $_POST['smiley_activate']) + { + $pref['smiley_activate'] = $_POST['smiley_activate']; + e107::getLog()->add($pref['smiley_activate'] ? 'EMOTE_02' : 'EMOTE_03', $pref['emotepack'], E_LOG_INFORMATIVE, ''); + save_prefs(); + $update = true; + + } + else + { + $mes->addInfo(LAN_NO_CHANGE); + } + +} + +e107::getRender()->tablerender($caption, $mes->render() . $text); + +/* get packs */ +require_once(e_HANDLER."file_class.php"); +$fl = e107::getFile(); +$emote = new emotec; +$one_pack = FALSE; +$filtered = e107::getParser()->filter($_POST); + +// Check for pack-related buttons pressed +foreach($filtered as $key => $value) +{ + if(strstr($key, "subPack_")) + { + $subpack = str_replace("subPack_", "", $key); + $emote->emoteConf($subpack); + break; + } + + if(strstr($key, "XMLPack_")) + { + $subpack = str_replace("XMLPack_", "", $key); + $emote->emoteXML($subpack); + break; + } + + if(strstr($key, "defPack_")) + { + $pref['emotepack'] = str_replace("defPack_", "", $key); + if(save_prefs()) + { + $mes->addSuccess(LAN_UPDATED); + } + else + { + $mes->addInfo(LAN_NO_CHANGE); + } + e107::getLog()->add('EMOTE_01', $pref['emotepack'], E_LOG_INFORMATIVE, ''); + break; + } + + if(strstr($key, "scanPack_")) + { + $one_pack = str_replace("scanPack_", "", $key); + break; + } +} + +$ns->tablerender($caption, $mes->render() . $text); + + +$check = TRUE; +//$check = $emote -> installCheck(); +$check = $emote->installCheck($one_pack); +if($check!==FALSE) +{ + $emote -> listPacks(); +} + + + +class emotec +{ + var $packArray; // Stores an array of all available emote packs (as subdirectory names) + + function emotec() + { + /* constructor */ + $fl = e107::getFile(); + $this -> packArray = $fl->get_dirs(e_IMAGE."emotes"); + + if(isset($_POST['sub_conf'])) + { // Update stored pack configuration + $this -> saveConf(); + } + } + + + // List available emote packs + function listPacks() + { + $pref = e107::getPref(); + $frm = e107::getForm(); + $fl = e107::getFile(); + $ns = e107::getRender(); + $mes = e107::getMessage(); + + $text = " + + + +
+
+
+
+ ".EMOLAN_1." + + + + + + + + + + + +
+ ".EMOLAN_4.": + +
+ ".$frm->checkbox('smiley_activate', 1, varset($pref['smiley_activate'],0))." +
+
+
+ ".$frm->admin_button('active','active','update',LAN_UPDATE)." +
+
+ +
+ "; + + $text .= " +
+
+
+ ".EMOLAN_13." + + + + + + + + + + + + + + + + + "; + + $reject = '~^emoteconf|\.html$|\.php$|\.txt$'; // Files to exclude + foreach($this -> packArray as $pack) + { + $can_scan = FALSE; + $emoteArray = $fl -> get_files(e_IMAGE.'emotes/'.$pack, $reject); + + $text .= " + + + + + + + "; + } + + $text .= " + +
".LAN_NAME."".EMOLAN_3."".LAN_STATUS."".LAN_OPTIONS."
{$pack} + "; + + foreach($emoteArray as $emote) + { + if (strstr($emote['fname'], ".pak") + || strstr($emote['fname'], ".xml") + || strstr($emote['fname'], "phpBB")) + { + $can_scan = TRUE; // Allow re-scan of config files + } + //elseif (!strstr($emote['fname'], ".txt") && !strstr($emote['fname'], ".bak") && !strstr($emote['fname'], ".html") && !strstr($emote['fname'], ".php") ) + else + { // Emote file found (might get other non-image files, but shouldn't) + $text .= " "; + } + } + + $text .= " + ".($pref['emotepack'] == $pack ? "".LAN_ACTIVE."" : "").""; + + + + + $text .= $frm->admin_button('subPack_'.$pack,'edit','default',LAN_CONFIGURE); + + if ($can_scan && ($pack != 'default')) + { + // $text .= ""; + $text .= $frm->admin_button('scanPack_'.$pack,'active','default',EMOLAN_26); + } + + $text .= $frm->admin_button('XMLPack_'.$pack,'submit','default',EMOLAN_28); + $text .= " +
+
+
+
+
+ + "; + + $ns->tablerender(EMOLAN_PAGE_TITLE, $mes->render().$text); + } + + + // Configure an individual emote pack + function emoteConf($packID) + { + global $e107, $sysprefs; + $frm = e107::getForm(); + $tp = e107::getParser(); + $fl = e107::getFile(); + $ns = e107::getRender(); + + $packID = $tp->filter($packID); + $corea = "emote_".$packID; + + $emotecode = $sysprefs -> getArray($corea); + $reject = '~^emoteconf|\.html$|\.php$|\.txt$|\.pak$|\.xml|\.phpBB'; // Files to exclude + $emoteArray = $fl -> get_files(e_IMAGE."emotes/".$packID, $reject); + + $eArray = array(); + foreach($emoteArray as $value) + { + $eArray[] = array('path' => $value['path'], 'fname' => $value['fname']); + } + + //XXX Not sure if we need to know rhe number of files found - count($eArray) -
Total ".count($eArray)." files found
+ $text = " +
+
+ ".LAN_EDIT." +
".$tp->lanVars(EMOLAN_31, count($eArray))."
+ + + + + + + + + + + + + + + "; + + foreach($eArray as $emote) + { + $ename = $emote['fname']; + $evalue = str_replace(".", "!", $ename); + $file_back = ''; + $text_back = ''; + + if (!isset($emotecode[$evalue])) + { + $file_back = '  '.EMOLAN_37.''; + } + elseif (!$emotecode[$evalue]) + { + $text_back = '  '.EMOLAN_38.''; + } + $text .= " + + + + + + "; + } + + $text .= " + +
".EMOLAN_5."".LAN_NAME."".EMOLAN_6." ( ".EMOLAN_7." )
".$ename."{$file_back} + {$text_back} +
+
+ "; + + + $text .= $frm->admin_button('sub_conf', 'no-value', 'update', LAN_SAVE); + $text .= $frm->admin_button('cancel','no-value', 'cancel' ,LAN_CANCEL); + + $text .= " +
+
+
"; + + $ns->tablerender(EMOLAN_PAGE_TITLE.SEP.LAN_EDIT.": '".$packID."'", $text); + } + + + // Generate an XML file - packname.xml in root emoticon directory + function emoteXML($packID, $strip_xtn = TRUE) + { + global $sysprefs; + $mes = e107::getMessage(); + $fl = e107::getFile(); + $tp = e107::getParser(); + + $packID = $tp->filter($packID); + + $fname = e_IMAGE."emotes/".$packID."/emoticons.xml"; + $backname = e_IMAGE."emotes/".$packID."/emoticons.bak"; + + $corea = "emote_".$packID; + $emotecode = $sysprefs -> getArray($corea); + + $reject = '~^emoteconf|\.html$|\.php$|\.txt$|\.pak$|\.xml|\.phpBB'; // Files to exclude + $emoteArray = $fl -> get_files(e_IMAGE."emotes/".$packID, $reject); + + $eArray = array(); + foreach($emoteArray as $value) + { + $eArray[] = $value['fname']; + } + + $f_string = "\n\n\n\n"; + + foreach($eArray as $emote) + { + // Optionally strip file extension + $evalue = str_replace(".", "!", $emote); + if ($strip_xtn) $ename = substr($emote,0,strrpos($emote,'.')); + $f_string .= "\n"; + foreach (explode(' ',$tp -> toForm($emotecode[$evalue])) as $v) + { + if (trim($v)) $f_string .= "\t{$v}\n"; + } + $f_string .= "\n"; + } + + $f_string .= "\n\n"; + + if (is_file($backname)) unlink($backname); // Delete any old backup + + if (is_file($fname)) rename($fname,$backname); + + if (file_put_contents($fname,$f_string) === FALSE) + { + $mes->addWarning(''.EMOLAN_30.':'.str_replace(e_IMAGE, e_IMAGE_ABS, $fname)); + } + else + { + $mes->addSuccess(''.EMOLAN_29.':'.str_replace(e_IMAGE, e_IMAGE_ABS, $fname)); + } + } + + + // Save configuration for an emote pack that's been edited + function saveConf() + { + $sql = e107::getDb(); + $tp = e107::getParser(); + + + $packID = $_POST['packID']; + unset($_POST['sub_conf'], $_POST['packID']); + $encoded_emotes = $tp->toDB($_POST); + // $tmp = addslashes(serialize($encoded_emotes)); + $tmp = e107::getArrayStorage()->WriteArray($encoded_emotes); + + if ($sql->db_Select("core", "*", "e107_name='emote_".$packID."'")) + { + e107::getMessage()->addAuto($sql->update("core", "`e107_value`='{$tmp}' WHERE `e107_name`='emote_".$packID."' "), 'update', LAN_SETSAVED, false, false); + } + else + { + e107::getMessage()->addAuto($sql->insert("core", "'emote_".$packID."', '$tmp' "), 'insert', LAN_SETSAVED, false, false); + } + } + + + // Identify currently selected emote pack. Read in any new ones + // Return false to disable listing of packs + function installCheck($do_one = FALSE) + { + global $e107; + $sql = e107::getDb(); + $fl = e107::getFile(); + $ns = e107::getRender(); + $mes = e107::getMessage(); + + // Pick up a list of emote packs from the database + $pack_local = array(); + if ($sql->select("core","*","`e107_name` LIKE 'emote_%'")) + { + while ($row = $sql->fetch()) + { + $pack_local[substr($row['e107_name'],6)] = TRUE; + } + } + + foreach($this -> packArray as $value) + { + if(strpos($value,' ')!==FALSE) + { // Highlight any directory names containing spaces - not allowed + $msg = " + ".EMOLAN_17." ".EMOLAN_18.": +
".LAN_NAME.": {$value}
+
".EMOLAN_20.": ".e_IMAGE_ABS."emotes/
+ "; + $mes->addError($msg); + $ns->tablerender(EMOLAN_PAGE_TITLE.' - '.EMOLAN_21, $mes->render()); + return FALSE; + } + + if (array_key_exists($value,$pack_local)) + { + unset($pack_local[$value]); + } + + if (($do_one == $value) || !$do_one && (!$sql -> db_Select("core", "*", "e107_name='emote_".$value."' "))) + { // Pack info not in DB, or to be re-scanned + $no_error = TRUE; + $File_type = EMOLAN_32.":"; + // Array of all files in the directory of the selected emote pack + $fileArray = $fl -> get_files(e_IMAGE."emotes/".$value); // We actually want all the files in the directory + $confFile = ''; + foreach($fileArray as $k => $file) + { + if(strstr($file['fname'], ".xml")) + { + $confFile = array('file' => $file['fname'], 'type' => "xml"); + } + else if(strstr($file['fname'], ".pak")) + { + $confFile = array('file' => $file['fname'], 'type' => "pak"); + } + else if(strstr($file['fname'], ".php")) + { + $confFile = array('file' => $file['fname'], 'type' => "php"); + } + if ($confFile) + { + unset($fileArray[$k]); + break; + } + } + + /* .pak file */ + if($confFile['type'] == "pak") + { + $filename = e_IMAGE."emotes/".$value."/".$confFile['file']; + $pakconf = file ($filename); + $contentArray = array(); + foreach($pakconf as $line) + { + if(trim($line) && strstr($line, "=+") && !strstr($line, ".txt") && !strstr($line, ".html") && !strstr($line, "cvs")) $contentArray[] = $line; + } + $confArray = array(); + foreach($contentArray as $pakline) + { + $tmp = explode("=+:", $pakline); + $confIC = str_replace(".", "!", $tmp[0]); + $confArray[$confIC] = trim($tmp[2]); + } + // $tmp = addslashes(serialize($confArray)); + $tmp = e107::serialize($confArray); + $File_type = EMOLAN_22.":"; + } + /* end */ + + /* .xml file */ + if($confFile['type'] == "xml") + { + $filename = e_IMAGE."emotes/".$value."/".$confFile['file']; + $contents = file_get_contents($filename); + $confArray = array(); + $xml_type = 0; + + if ((strpos($contents, "") !== FALSE) && (strpos($contents, "") !== FALSE)) + { // xep-0038 format + /* Example: + + :-) + :) + happy.png + choir.wav + */ + preg_match_all("#\(.*?)\<\/icon\>#si", $contents, $match); + + $xml_type = 1; + // $match[0] - complete emoticon entry + // $match[1] - match string and object specification + $item_index = 1; + } + elseif (strpos($contents, ""; + preg_match_all("#\(.*?)\<\/emoticon\>#si", $contents, $match); + + $xml_type = 2; + // $match[0] - complete emoticon entry + // $match[1] - filename (may or may not not have file extension/suffix) + // $match[2] - match string(s) representing emote + $item_index = 2; + } + + if ($xml_type) + { + for($a=0; $a < count($match[0]); $a++) + { + $e_file = ''; + switch ($xml_type) + { + case 1 : // xep-0038 + // Pull out a file name (only support first image type) - its in $fmatch[1] + if (preg_match("#\(.*?)\<\/object\>#si",$match[1][$a],$fmatch)) + { + $e_file = $fmatch[1]; +// echo "xep-0038 file: ".$e_file."
"; + // Pull out all match strings - need to pick out any language definitions for posterity + // but currently accept all language strings + preg_match_all("#\|\s*?xml\:lang\=\"(.*?)\"\>)(.*?)\<\/text\>#si", $match[1][$a], $match2); + // $match2[1] is the languages + // $match2[2] is the match strings + $codet = implode(" ",$match2[2]); + } + break; + case 2 : + $e_file = $match[1][$a]; + // Now pull out all the 'match' strings + preg_match_all("#\(.*?)\<\/string\>#si", $match[2][$a], $match2); + $codet = implode(" ",$match2[1]); + break; + } + // $e_file has the emote file name + // $match2 has an array of substitution strings + + + $file = ''; + foreach($fileArray as $emote) + { // Check that the file exists + if (strpos($e_file,".") === FALSE) + { // File extension not specified - accept any file extension for match + if(strpos($emote['fname'], $e_file.".") === 0) + { + $file = str_replace(".", "!", $emote['fname']); + break; + } + } + else + { // File extension specified - do simple match + if($emote['fname'] == $e_file) + { + $file = str_replace(".", "!", $emote['fname']); + break; + } + } + } + // Only add if the file exists. OK if no definition - might want to be added + if ($file) + { + $confArray[$file] = $codet; + } + } + } + else + { + //echo "Unsupported XML File Format

"; + $mes->addWarning(EMOLAN_33); + $no_error = FALSE; + } + + + // Save pack info in the database + // $tmp = addslashes(serialize($confArray)); + $tmp = e107::getArrayStorage()->WriteArray($confArray); + $File_type = EMOLAN_23.":"; + } + + if($confFile['type'] == "php") + { + include_once(e_IMAGE."emotes/".$value."/".$confFile['file']); + $File_type = EMOLAN_24.":"; + $tmp = $_emoteconf; // Use consistent name + } + + if ($no_error) + { + if ($do_one) + { // Assume existing pack + $sql->update("core", "`e107_value`='{$tmp}' WHERE `e107_name`='emote_".$value."'"); + } + else + { // Assume new pack + $sql->insert("core", "'emote_".$value."', '{$tmp}' "); + } + $mes->addInfo("{$File_type} '{$value}'"); + } + else + { // Error occurred + $mes->addError(EMOLAN_27.": '{$value}'"); + } + } + } + + + + if (count($pack_local)) + { + foreach ($pack_local as $p => $d) + { + if($p == '0') + { + $p = ''; + } + + if($sql->delete("core","`e107_name` = 'emote_{$p}'")) + { + $mes->addInfo(EMOLAN_34.":".$p.EMOLAN_35); + } + } + } + + return TRUE; + } + +} +require_once("footer.php"); +/** + * Handle page DOM within the page header + * + * @return string JS source + */ +function headerjs() +{ +/* require_once(e_HANDLER.'js_helper.php'); + + $ret = " + + + "; + + return $ret;*/ +} ?> \ No newline at end of file diff --git a/e107_admin/fileinspector.php b/e107_admin/fileinspector.php index 23bb95988..38a9ec7f2 100755 --- a/e107_admin/fileinspector.php +++ b/e107_admin/fileinspector.php @@ -1,1710 +1,1710 @@ -debug = FALSE; -//require_once(e_HANDLER.'form_handler.php'); -$DOCS_DIRECTORY = $HELP_DIRECTORY; // Give a sensible, albeit probably invalid, value -if (substr($HELP_DIRECTORY,-5,5) == 'help/') -{ - $DOCS_DIRECTORY = substr($HELP_DIRECTORY,0,-5); // Whatever $HELP_DIRECTORY is set to, assume docs are in a subdirectory called 'help' off it -} -$maindirs = array('admin' => $ADMIN_DIRECTORY, 'files' => $FILES_DIRECTORY, 'images' => $IMAGES_DIRECTORY, 'themes' => $THEMES_DIRECTORY, 'plugins' => $PLUGINS_DIRECTORY, 'handlers' => $HANDLERS_DIRECTORY, 'languages' => $LANGUAGES_DIRECTORY, 'downloads' => $DOWNLOADS_DIRECTORY, 'docs' => $DOCS_DIRECTORY); -foreach ($maindirs as $maindirs_key => $maindirs_value) { - $coredir[$maindirs_key] = substr($maindirs_value, 0, -1); -} - -require_once('core_image.php'); - -//$rs = new form; -set_time_limit(18000); -$e_sub_cat = 'fileinspector'; - - -if(isset($_GET['scan'])) -{ - - session_write_close(); - while (@ob_end_clean()); - - - //header("Content-type: text/html; charset=".CHARSET, true); - //$css_file = file_exists(e_THEME.$pref['admintheme'].'/'.$pref['admincss']) ? e_THEME.$pref['admintheme'].'/'.$pref['admincss'] : e_THEME.$pref['admintheme'].'/'.$pref['admincss']; -// $fi = new file_inspector; - - $fi = e107::getSingleton('file_inspector'); - - - echo " - - - Results - - ".$fi->headerCss()." ".headerjs()." - \n"; - -// define('e_IFRAME', true); -// require_once(e_ADMIN."auth.php"); - - - - - - // echo "
loading.."; - - // echo ".."; - //flush(); - - $_POST = $_GET; - - if(vartrue($_GET['exploit'])) - { - $fi->exploit(); - } - else - { - $fi->scan_results(); - } - -// require_once(e_ADMIN."footer.php"); - - echo ""; - - exit(); - -} -else -{ - // $fi = new file_inspector; - $fi = e107::getSingleton('file_inspector'); - - - - - - require_once(e_ADMIN.'auth.php'); - - -// if (e_QUERY) { - // $fi -> snapshot_interface(); - //} - - if (varset($_POST['scan'])) - { - $fi->exploit_interface(); - $fi->scan_config(); - } - elseif($_GET['mode'] == 'run') - { - $mes = e107::getMessage(); - $mes->addInfo(FR_LAN_32);//Run a Scan first - echo $mes->render(); - } - else - { - $fi->scan_config(); - } -} - - - - -class file_inspector { - - var $root_dir; - var $files = array(); - var $parent; - var $count = array(); - var $results = 0; - var $totalFiles = 0; - var $coredir = array(); - var $progress_units = 0; - private $langs = array(); - private $lang_short = array(); - - - private $excludeFiles = array( '.', '..','/','.svn', 'CVS' ,'Thumbs.db', '.git'); - - private $knownSecurityIssues = array('htmlarea', 'e107_docs/docs.php'); -// private $icon = array(); - private $iconTag = array(); - - private $options = array( - 'core' => '', - 'type' =>'list', - 'missing' => 0, - 'noncore' => 9, - 'nolang' => 1, - 'oldcore' => 0, - 'integrity' => 1, - 'regex' => 0, - 'mod' => '', - 'num' => 0, - 'line' => 0 - ); - - - function setOptions($post) - { - foreach($this->options as $k=>$v) - { - if(isset($post[$k])) - { - $this->options[$k] = $post[$k]; - } - } - - } - - - function __construct() - { - - $lng = e107::getLanguage(); - $langs = $lng->installed(); - - if(isset($_GET['scan'])) - { - $this->setOptions($_GET); - } - - $lang_short = array(); - foreach($langs as $k=>$val) - { - if($val == "English") // Core release language, so ignore it. - { - unset($langs[$k]); - continue; - } - - $lang_short[] = $lng->convert($val); - } - - $this->langs = $langs; - $this->lang_short = $lang_short; - - - //TODO LAN - - $this->glyph = array( - 'folder_close' => array(''), - 'folder_up' => array(''), - 'folder_root' => array(''), - - 'warning' => array(''), - 'info' => array(''), - 'fileinspector' => array(''), - - 'folder' => array(''), - 'folder_check' => array('', FC_LAN_24 ), - 'folder_fail' => array('', FC_LAN_25 ), - 'folder_missing' => array('', FC_LAN_26 ), - 'folder_warning' => array(''), - 'folder_old' => array('', FC_LAN_27 ), - 'folder_old_dir' => array(''), - 'folder_unknown' => array('', FC_LAN_28 ), - - 'file_check' => array('', FC_LAN_29), - 'file_core' => array('', FC_LAN_30), - 'file_fail' => array('', FC_LAN_31 ), - 'file_missing' => array('', FC_LAN_32 ), - 'file_old' => array('', FC_LAN_33 ), - 'file_uncalc' => array('', FC_LAN_34 ), - 'file_warning' => array('', FC_LAN_35 ), - 'file_unknown' => array('', FC_LAN_36 ), - - - - ); - - foreach($this->glyph as $k=>$v) - { - - $this->iconTag[$k] = $this->glyph[$k][0]; - - } - - - global $e107,$core_image; - - //$this->totalFiles = count($core_image,COUNT_RECURSIVE); - $this->countFiles($core_image); - - $this -> root_dir = $e107 -> file_path; - if (substr($this -> root_dir, -1) == '/') - { - $this -> root_dir = substr($this -> root_dir, 0, -1); - } - - if ($_POST['core'] == 'fail') - { - $_POST['integrity'] = TRUE; - } - - if (MAGIC_QUOTES_GPC && vartrue($_POST['regex'])) - { - $_POST['regex'] = stripslashes($_POST['regex']); - } - - if ($_POST['regex']) { - if ($_POST['core'] == 'fail') { - $_POST['core'] = 'all'; - } - $_POST['missing'] = 0; - $_POST['integrity'] = 0; - } - } - - - private function opt($key) - { - return $this->options[$key]; - } - - - // Find the Total number of core files before scanning begins. - function countFiles($array) - { - foreach($array as $k=>$val) - { - if(is_array($val)) - { - $this->countFiles($val); - } - elseif($val) - { - $this->totalFiles++; - } - - } - } - - - private function getDiz($key) - { - if(!empty($this->glyph[$key][1])) - { - return $this->glyph[$key][1]; - } - - return $key; - - } - - - public function getLegend() - { - return $this->glyph; - - } - - - function renderHelp() - { - - $text = ""; - foreach($this->iconTag as $k=>$v) - { - $text .= ""; - - } - $text .= "
".$v."".$k."
"; - // echo $text; - } - - - function scan_config() - { - - $frm = e107::getForm(); - $ns = e107::getRender(); - $pref = e107::pref('core'); - - - - - if($_GET['mode'] == 'run') - { - return; - } - - - $tab = array(); - - $head = "
-
"; - - $text = " - "; - - /* $text .= " - - - ";*/ - - $coreOpts = array('full'=>FC_LAN_6, 'all'=>LAN_ALL, 'none'=> LAN_NONE); - - $text .= " - - - "; - - - $dispOpt = array('tree'=>FC_LAN_15, 'list'=>LAN_LIST); - $text .= " - - - - "; - - - - $text .= " - - - "; - - $text .= " - - - "; - - $text .= " - - - "; - - - - - $text .= " - - "; - - $text .= "
".LAN_OPTIONS."
- ".LAN_SHOW." ".FC_LAN_5.": - ".$frm->select('core',$coreOpts,$_POST['core'])."
- ".FC_LAN_14.": - ".$frm->select('type', $dispOpt, $_POST['type'])."
- ".LAN_SHOW." ".FC_LAN_13.": - - ".LAN_YES."   - ".LAN_NO."   -
- ".LAN_SHOW." ".FC_LAN_7.": - - ".LAN_YES."   - ".LAN_NO."   - ".FC_LAN_23."   -
- ".LAN_SHOW." ".FC_LAN_21.": - - ".LAN_YES."   - ".LAN_NO."   -
- ".FC_LAN_8.": - - ".LAN_YES."   - ".LAN_NO."   -
"; - - $tab['basic'] = array('caption'=>LAN_OPTIONS, 'text'=>$text); - - - if ($pref['developer']) { - - $text2 = ""; - /* $text2 .= " - - ";*/ - - $text2 .= " - - - "; - - $text2 .= " - - - "; - - $text2 .= " - - - "; - - $text2 .= " -
".FC_LAN_17."
- ".FC_LAN_18.": - - ## -
- ".FC_LAN_19.": - - -
- ".FC_LAN_20.": - - -
"; - - $tab['advanced'] = array('caption'=>FC_LAN_17, 'text'=>$text2); - } - - - $tabText = e107::getForm()->tabs($tab); - - - - - - $foot = " -
- ".$frm->admin_button('scan', LAN_GO, 'other')." -
-
-
"; - - $text = $head.$tabText.$foot; - - $ns -> tablerender(FC_LAN_1, $text); - - } - - function scan($dir, $image) - { - - - $handle = opendir($dir.'/'); - while (false !== ($readdir = readdir($handle))) - { - - if ($readdir != '.' && $readdir != '..' && $readdir != '/' && $readdir != 'CVS' && $readdir != 'Thumbs.db' && (strpos('._', $readdir) === FALSE)) - { - $path = $dir.'/'.$readdir; - if (is_dir($path)) - { - $dirs[$path] = $readdir; - } - elseif (!isset($image[$readdir])) - { - $files[$readdir] = $this -> checksum($path, TRUE); - } - } - } - closedir($handle); - - if (isset($dirs)) { - ksort ($dirs); - foreach ($dirs as $dir_path => $dir_list) { - $list[$dir_list] = ($set = $this -> scan($dir_path, $image[$dir_list])) ? $set : array(); - } - } - - if (isset($files)) { - ksort ($files); - foreach ($files as $file_name => $file_list) { - $list[$file_name] = $file_list; - } - } - - return $list; - } - - // Given a full path and filename, looks it up in the list to determine valid actions; returns: - // 'check' - file is expected to be present, and validity is to be checked - // 'ignore' - file may or may not be present - check its validity if found, but not an error if missing - // 'uncalc' - file must be present, but its integrity cannot be checked. - // 'nocalc' - file may be present, but its integrity cannot be checked. Not an error if missing - function check_action($dir, $name) - { - global $coredir; - - if ($name == 'e_inspect.php') { return 'nocalc'; } // Special case for plugin integrity checking - - $filename = $dir.'/'.$name; - $admin_dir = $this->root_dir.'/'.$coredir['admin'].'/'; - $image_dir = $this->root_dir.'/'.$coredir['images'].'/'; - $test_list = array(); - - // Files that are unable to be checked - $test_list[$admin_dir.'core_image.php'] = 'uncalc'; - $test_list[$this->root_dir.'/e107_config.php'] = 'uncalc'; - - // Files that are likely to be renamed by user - $test_list[$admin_dir.'filetypes_.php'] = 'ignore'; - $test_list[$this->root_dir.'/e107.htaccess'] = 'ignore'; - $test_list[$this->root_dir.'/e107.robots.txt'] = 'ignore'; - - if (isset($test_list[$filename])) { return $test_list[$filename]; } - return 'check'; - } - - - // This function does the real work - // $list - - // $deprecated - // $level - // $dir - // &$tree_end - // &$parent_expand - function inspect($list, $deprecated, $level, $dir, &$tree_end = null, &$parent_expand = null) - { - global $coredir; - - $sub_text = ''; - $langs = $this->langs; - $lang_short = $this->lang_short; - - - unset ($childOut); - $parent_expand = false; - if (substr($dir, -1) == '/') - { - $dir = substr($dir, 0, -1); - } - $dir_id = dechex(crc32($dir)); - $this -> files[$dir_id]['.']['level'] = $level; - $this -> files[$dir_id]['.']['parent'] = $this -> parent; - $this -> files[$dir_id]['.']['file'] = $dir; - $directory = $level ? basename($dir) : SITENAME; - $level++; - - // - - - - $this->sendProgress(vartrue($this->count['core']['num']),$this->totalFiles,FR_LAN_1); - - foreach ($list as $key => $value) - { - // $dir_icon = 'fileinspector'; // default as unknown - $this -> parent = $dir_id; - if (is_array($value)) - { // Entry is a subdirectory - recurse another level - $path = $dir.'/'.$key; - $child_open = false; - $child_end = true; - $dir_icon = 'folder_check'; - $sub_text .= $this -> inspect($value, $deprecated[$key], $level, $path, $child_end, $child_expand); - $tree_end = false; - if ($child_expand) - { - $parent_expand = true; - $last_expand = true; - } - } - else - { - $this->sendProgress(vartrue($this->count['core']['num']),$this->totalFiles,FR_LAN_1); - $path = $dir.'/'.$key; - - $fid = strtolower($key); - $this -> files[$dir_id][$fid]['file'] = ($_POST['type'] == 'tree') ? $key : $path; - - if (($this -> files[$dir_id][$fid]['size'] = filesize($path)) !== false) - { // We're checking a file here - if ($this->opt('core') != 'none') - { // Look at core files - $this -> count['core']['num']++; - $this -> count['core']['size'] += $this -> files[$dir_id][$fid]['size']; - - if ($_POST['regex']) // Developer prefs activated - search file contents according to regex - { // TODO Max out of Memory when used - $file_content = file($path); // Get contents of file - - if (($this -> files[$dir_id][$fid]['size'] = filesize($path)) !== FALSE) - { - if ($this -> files[$dir_id][$fid]['lines'] = preg_grep("#".$_POST['regex']."#".$_POST['mod'], $file_content)) - { // Search string found - add file to list - $this -> files[$dir_id][$fid]['file'] = ($_POST['type'] == 'tree') ? $key : $path; - $this -> files[$dir_id][$fid]['icon'] = 'file_core'; - $dir_icon = 'fileinspector'; - $parent_expand = TRUE; - $this -> results++; - } - else - { // Search string not found - discard from list - unset($this -> files[$dir_id][$fid]); - $known[$dir_id][$fid] = true; - $dir_icon = ($dir_icon == 'fileinspector') ? 'folder_unknown': $dir_icon ; - } - } - } - else - { - if ($this->opt('integrity')) - { // Actually check file integrity - switch ($this_action = $this->check_action($dir,$key)) - { - case 'ignore' : - case 'check' : - if ($this->checksum($path) != $value) - { - $this -> count['fail']['num']++; - $this -> count['fail']['size'] += $this -> files[$dir_id][$fid]['size']; - $this -> files[$dir_id][$fid]['icon'] = 'file_fail'; - $dir_icon = 'folder_fail'; - $parent_expand = TRUE; - } - else - { - $this -> count['pass']['num']++; - $this -> count['pass']['size'] += $this -> files[$dir_id][$fid]['size']; - - if ($this->opt('core') != 'fail') - { - $this -> files[$dir_id][$fid]['icon'] = 'file_check'; - $dir_icon = ($dir_icon == 'folder_fail' || $dir_icon == 'folder_missing') ? $dir_icon : 'folder_check'; - } - else - { - unset($this -> files[$dir_id][$fid]); - $known[$dir_id][$fid] = true; - - } - } - break; - case 'uncalc' : - case 'nocalc' : - $this -> count['uncalculable']['num']++; - $this -> count['uncalculable']['size'] += $this -> files[$dir_id][$fid]['size']; - if ($this->opt('core') != 'fail') - { - $this -> files[$dir_id][$fid]['icon'] = 'file_uncalc'; - - } - else - { - unset($this -> files[$dir_id][$fid]); - $known[$dir_id][$fid] = true; - } - break; - } - } - else - { // Just identify as core file - $this -> files[$dir_id][$fid]['icon'] = 'file_core'; - } - } - } - else - { - unset ($this -> files[$dir_id][$fid]); - $known[$dir_id][$fid] = true; - } - } - else if ($this->opt('missing')) - { - switch ($this_action = $this->check_action($dir,$key)) - { - case 'check' : - case 'uncalc' : - $this -> count['missing']['num']++; - $this -> files[$dir_id][$fid]['icon'] = 'file_missing'; - $dir_icon = ($dir_icon == 'folder_fail') ? $dir_icon : 'folder_missing'; - $parent_expand = TRUE; - break; - case 'ignore' : - case 'nocalc' : - // These files can be missing without error - delete from the list - unset ($this -> files[$dir_id][$fid]); - $known[$dir_id][$fid] = true; - break; - } - } - else - { - unset ($this -> files[$dir_id][$fid]); - } - } - } - - if ($this->opt('noncore') || $this->opt('oldcore')) - { - - - - if(!$handle = opendir($dir.'/')) - { - //e107::getMessage()->addInfo("Couldn't Open : ".$dir); - } - - while (is_resource($handle) && false !== ($readdir = readdir($handle))) - { - // $prog_count = $this->count['unknown']['num'] + $this->count['deprecated']['num']; - // $this->sendProgress($prog_count,$this->totalFiles,FR_LAN_1); - - if (!in_array($readdir,$this->excludeFiles) && (strpos('._', $readdir) === false)) - { - - if (is_dir($dir.'/'.$readdir)) - { - if (!isset($list[$readdir]) && ($level > 1 || $readdir == 'e107_install')) - { - $child_open = false; - $child_end = true; - $sub_text .= $this->inspect(array(), $deprecated[$readdir], $level, $dir.'/'.$readdir, $child_end, $child_expand); - $tree_end = false; - if ($child_expand) - { - $parent_expand = true; - $last_expand = true; - } - } - - - } - else - { - - - - if($this->opt('nolang') && !empty($langs) && !empty($lang_short)) // Hide Non-core Languages. - { - - // PHP Lang files. - $lreg = "/[\/_](".implode("|",$langs).")/"; - if(preg_match($lreg, $dir.'/'.$readdir)) - { - continue; - } - - // TinyMce Lang files. - $lregs = "/[\/_](".implode("|",$lang_short).")_dlg\.js/"; - if(preg_match($lregs, $dir.'/'.$readdir)) - { - continue; - } - - // PhpMailer Lang Files. - $lregsm = "/[\/_]phpmailer\.lang-(".implode("|",$lang_short).")\.php/"; - if(preg_match($lregsm, $dir.'/'.$readdir)) - { - continue; - } - } - - $aid = strtolower($readdir); - - if (!isset($this -> files[$dir_id][$aid]['file']) && !$known[$dir_id][$aid]) - { - if ($this->checkKnownSecurity($dir.'/'.$readdir) === false) - { - if (isset($deprecated[$readdir])) - { - if ($this->opt('oldcore')) - { - $this -> files[$dir_id][$aid]['file'] = ($_POST['type'] == 'tree') ? $readdir : $dir.'/'.$readdir; - $this -> files[$dir_id][$aid]['size'] = filesize($dir.'/'.$readdir); - $this -> files[$dir_id][$aid]['icon'] = 'file_old'; - $this -> count['deprecated']['num']++; - $this -> count['deprecated']['size'] += $this -> files[$dir_id][$aid]['size']; - $dir_icon = 'folder_old'; - } - } - else - { - if ($this->opt('noncore')) - { - $this -> files[$dir_id][$aid]['file'] = ($_POST['type'] == 'tree') ? $readdir : $dir.'/'.$readdir; - $this -> files[$dir_id][$aid]['size'] = filesize($dir.'/'.$readdir); - //echo "
dir: ".$dir.'/'.$readdir. " ( ".$this -> files[$dir_id][$aid]['size'].")"; - $this -> files[$dir_id][$aid]['icon'] = 'file_unknown'; - $this -> count['unknown']['num']++; - $this -> count['unknown']['size'] += $this -> files[$dir_id][$aid]['size']; - } - } - } - else - { - $this -> files[$dir_id][$aid]['file'] = ($_POST['type'] == 'tree') ? $readdir : $dir.'/'.$readdir; - $this -> files[$dir_id][$aid]['size'] = filesize($dir.'/'.$readdir); - $this -> files[$dir_id][$aid]['icon'] = 'file_warning'; - $this -> count['warning']['num']++; - $this -> count['warning']['size'] += $this -> files[$dir_id][$aid]['size']; - $this -> count['deprecated']['num']++; - $this -> count['deprecated']['size'] += $this -> files[$dir_id][$aid]['size']; - $dir_icon = 'folder_warning'; - $parent_expand = TRUE; - } - - $regexOpt = $this->opt('regex'); - if (!empty($regexOpt)) - { - $file_content = file($dir.'/'.$readdir); - if ($this -> files[$dir_id][$aid]['lines'] = preg_grep("#".$_POST['regex']."#".$_POST['mod'], $file_content)) - { - $dir_icon = 'fileinspector'; - $parent_expand = TRUE; - $this -> results++; - } - else - { - unset($this -> files[$dir_id][$aid]); - $dir_icon = ($dir_icon == 'fileinspector') ? $dir_icon : 'folder'; - } - } - else - { - if (isset($deprecated[$readdir])) - { - if ($this->opt('oldcore')) - { - $dir_icon = ($dir_icon == 'folder_warning' || $dir_icon == 'folder_fail' || $dir_icon == 'folder_missing' ) ? $dir_icon : 'folder_old'; - $parent_expand = TRUE; - } - } - else - { - if ($this->opt('noncore')) - { - $dir_icon = ($dir_icon == 'folder_warning' || $dir_icon == 'folder_fail' || $dir_icon == 'folder_missing' || $dir_icon == 'folder_old' || $dir_icon == 'folder_old_dir') ? $dir_icon : 'folder_unknown'; - $parent_expand = TRUE; - } - } - } - } else if ($this->opt('core') == 'none') { - unset($this -> files[$dir_id][$aid]); - } - } - } - } - closedir($handle); - - } - - $this->sendProgress($this->count['core']['num'],$this->totalFiles,FR_LAN_1); - - $dir_icon = $dir_icon ? $dir_icon : 'folder_unknown'; - // $icon = ""; - - $icon = $this->iconTag[$dir_icon]; - - $tp = e107::getParser(); - - $imgBlank = $tp->toImage('{e_IMAGE}fileinspector/blank.png', array( - 'alt' => '', - 'legacy' => '{e_IMAGE}fileinspector/', - 'w' => 9, - 'h' => 9, - 'class' => 'c', - )); - - $imgExpand = $tp->toImage('{e_IMAGE}fileinspector/expand.png', array( - 'alt' => '', - 'legacy' => '{e_IMAGE}fileinspector/', - 'w' => 15, - 'class' => 'e', - 'id' => 'e_' . $dir_id, - )); - - $imgContract = $tp->toImage('{e_IMAGE}fileinspector/contract.png', array( - 'alt' => '', - 'legacy' => '{e_IMAGE}fileinspector/', - 'w' => 15, - 'class' => 'e', - 'id' => 'e_' . $dir_id, - )); - - $hide = ($last_expand && $dir_icon != 'folder_core') ? "" : "style='display: none'"; - - $text = '
'; - $text .= $tree_end ? $imgBlank : '' . ($hide ? $imgExpand : $imgContract) . ''; - $text .= ' ' . $icon . ' ' . $directory . ''; - $text .= $tree_end ? '' : '
' . $sub_text . '
'; - $text .= '
'; - - $this -> files[$dir_id]['.']['icon'] = $dir_icon; - - return $text; - } - - private function checkKnownSecurity($path) - { - - foreach($this->knownSecurityIssues as $v) - { - if(strpos($path, $v) !== false) - { - return true; - } - } - - return false; - } - - - - function scan_results() - { - global $ns, $rs, $core_image, $deprecated_image; - $scan_text = $this -> inspect($core_image, $deprecated_image, 0, $this -> root_dir); - - - $this->sendProgress($this->totalFiles,$this->totalFiles,'      '); - - echo "
 
"; - - if ($this->opt('type') == 'tree') - { - $text = "
- - - - "; - - $text .= ""; - - $text .= " - - "; - - $text .= "
".FR_LAN_2."
-
- ".$scan_text." -
-
"; - } - else - { - $text = "
- - - - "; - - $text .= " - - -
".FR_LAN_2."
"; - } - - $text .= ""; - - if ($this->opt('type') == 'tree') - { - $text .= " - "; - } - else - { - $text .= ""; - } - - if ($this->opt('core') != 'none') - { - $text .= " - "; - } - if ($this->opt('missing')) - { - $text .= ""; - } - if ($this->opt('noncore')) - { - $text .= ""; - } - if ($this->opt('oldcore')) - { - $text .= ""; - } - if ($this->opt('core') == 'all') - { - $text .= ""; - } - - if ($this -> count['warning']['num']) - { - $text .= ""; - $text .= ""; - - $text .= ""; - - $text .= ""; - - } - if ($this->opt('integrity') && ($this->opt('core') != 'none')) - { - $integrity_icon = $this -> count['fail']['num'] ? 'integrity_fail.png' : 'integrity_pass.png'; - $integrity_text = $this -> count['fail']['num'] ? '( '.$this -> count['fail']['num'].' '.FR_LAN_19.' )' : '( '.FR_LAN_20.' )'; - $text .= ""; - $text .= ""; - - $text .= ""; - $text .= ""; - $text .= ""; - - $text .= ""; - - $text .= ""; - - $text .= ""; - } - - if ($this->opt('type') == 'tree' && !$this -> results && $this->opt('regex')) - { - $text .= " - "; - } - - $text .= "
".FR_LAN_3." root_dir))."')\"> -
".FR_LAN_3."
".$this->iconTag['file_core']." ".FC_LAN_5.": ".($this -> count['core']['num'] ? $this -> count['core']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['core']['size'], 2)."
".$this->iconTag['file_missing']." ".FC_LAN_13.": ".($this -> count['missing']['num'] ? $this -> count['missing']['num'] : LAN_NONE)." 
".$this->iconTag['file_unknown']." ".FC_LAN_7.": ".($this -> count['unknown']['num'] ? $this -> count['unknown']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['unknown']['size'], 2)."
".$this->iconTag['file_old']." ".FR_LAN_24.": ".($this -> count['deprecated']['num'] ? $this -> count['deprecated']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['deprecated']['size'], 2)."
".$this->iconTag['file']." ".FR_LAN_6.": ".($this -> count['core']['num'] + $this -> count['unknown']['num'] + $this -> count['deprecated']['num'])." ".$this -> parsesize($this -> count['core']['size'] + $this -> count['unknown']['size'] + $this -> count['deprecated']['size'], 2)."
 
- ".$this->iconTag['warning']." ".FR_LAN_26."
".$this->iconTag['file_warning']." ".FR_LAN_28.": ".($this -> count['warning']['num'] ? $this -> count['warning']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['warning']['size'], 2)."
".FR_LAN_27."
 
".FR_LAN_7." ".$integrity_text."
".$this->iconTag['file_check']." ".FR_LAN_8.": ".($this -> count['pass']['num'] ? $this -> count['pass']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['pass']['size'], 2)."
".$this->iconTag['file_fail']." ".FR_LAN_9.": ".($this -> count['fail']['num'] ? $this -> count['fail']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['fail']['size'], 2)."
".$this->iconTag['file_uncalc']." ".FR_LAN_25.": ".($this -> count['uncalculable']['num'] ? $this -> count['uncalculable']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['uncalculable']['size'], 2)."
 
".$this->iconTag['info']." ".FR_LAN_10.": 
- -

".FR_LAN_23."
"; - - if ($this->opt('type') != 'tree') - { - $text .= "
- "; - if (!$this -> results && $this->opt('regex')) - { - $text .= ""; - } - - - // print_a($this -> files); - } - - - - - foreach ($this -> files as $dir_id => $fid) - { - - // $this->sendProgress($cnt,$this->totalFiles,$path); - - ksort($fid); - $text .= ($this->opt('type') == 'tree') ? "
".FR_LAN_23."
" : ""; - $initial = FALSE; - foreach ($fid as $key => $stext) - { - - // print_a($stext); - - $iconKey = $stext['icon']; - - if (!$initial) - { - if ($this->opt('type') == 'tree') - { - - $rootIconKey = ($stext['level'] ? "folder_up" : "folder_root"); - - $text .= " - "; - } - } - else - { - if ($this->opt('type') != 'tree') - { - $stext['file'] = str_replace($this -> root_dir."/", "", $stext['file']); - } - - $text .= $this->renderRow($stext); - - - } - $initial = TRUE; - } - $text .= ($this->opt('type') == 'tree') ? "" : ""; - } - - if ($this->opt('type') != 'tree') { - $text .= "
"; - } - - $text .= "
-
"; - - echo e107::getMessage()->render(); - echo $text; - - - //$ns -> tablerender(FR_LAN_1.'...', $text); - - } - - - - - function renderRow($stext) - { - - $mode = $this->opt('core'); - - $iconKey = $stext['icon']; - - // return "".$mode." ( ".$iconKey.")"; - - - if($mode == 'full' && $iconKey == 'file_check' ) - { - return ''; - } - - if($mode == 'none') - { - // return ''; - } - - - $text = ''; - $text .= " - - getDiz($iconKey)."\">".$this->iconTag[$iconKey]." ".$stext['file']." "; - - if ($this->opt('regex')) - { - if ($this->opt('num') || $this->opt('line')) - { - $text .= "
"; - } - - foreach ($stext['lines'] as $rkey => $rvalue) - { - if ($this->opt('num')) - { - $text .= "[".($rkey + 1)."] "; - } - - if ($this->opt('line')) - { - $text .= htmlspecialchars($rvalue)."
"; - } - } - - $text .= "
"; - } - else - { - $text .= " - ".$this -> parsesize($stext['size']); - } - - $text .= ""; - - return $text; - } - - - - - - - - - - function create_image($dir) { - global $core_image, $deprecated_image,$coredir; - - foreach ($coredir as $trim_key => $trim_dirs) { - $search[$trim_key] = "'".$trim_dirs."'"; - $replace[$trim_key] = "\$coredir['".$trim_key."']"; - } - - $data = " scan($dir) : $core_image; - $image_array = var_export($scan_current, true); - $image_array = str_replace($search, $replace, $image_array); - $data .= "\$core_image = ".$image_array.";\n\n"; - - $scan_deprecated = ($_POST['snaptype'] == 'deprecated') ? $this -> scan($dir, $core_image) : $deprecated_image; - $image_array = var_export($scan_deprecated, true); - $image_array = str_replace($search, $replace, $image_array); - $data .= "\$deprecated_image = ".$image_array.";\n\n"; - - $data .= "?>"; - $fp = fopen(e_ADMIN.'core_image.php', 'w'); - fwrite($fp, $data); - } - - function snapshot_interface() - { - $ns = e107::getRender(); - $frm = e107::getRender(); - $text = ""; - - if (isset($_POST['create_snapshot'])) - { - $this -> create_image($_POST['snapshot_path']); - $text = "
-
- snapshot_interface - - - "; - - $text .= " - - - - - -
Snapshot Created
- The snapshot (".e_ADMIN."core_image.php) was successfully created. -
".$frm->admin_button('main_page', 'Return To Main Page', 'submit')."
-
-

"; - } - - $text .= "
-
- - - - "; - - $text .= " - - - - - - - - - - - -
Create Snapshot
- Absolute path of root directory to create image from: - - root_dir)."' /> -
- Create snapshot of current or deprecated core files: - - Current   - Deprecated   -
".$frm->admin_button('create_snapshot', 'Create Snapshot', 'create')."
-
-
"; - - $ns -> tablerender('Snapshot', $text); - - } - - function checksum($filename) - { - $checksum = md5(str_replace(array(chr(13),chr(10)), "", file_get_contents($filename))); - return $checksum; - } - - function parsesize($size, $dec = 0) { - $size = $size ? $size : 0; - $kb = 1024; - $mb = 1024 * $kb; - $gb = 1024 * $mb; - $tb = 1024 * $gb; - if ($size < $kb) { - return $size." ".CORE_LAN_B; - } else if($size < $mb) { - return round($size/$kb)." ".CORE_LAN_KB; - } else if($size < $gb) { - return round($size/$mb, $dec)." ".CORE_LAN_MB; - } else if($size < $tb) { - return round($size/$gb, $dec)." ".CORE_LAN_GB; - } else { - return round($size/$tb, $dec)." ".CORE_LAN_TB; - } - } - - function regex_match($file) { - $file_content = file_get_contents($file); - $match = preg_match($_POST['regex'], $file_content); - - return $match; - } - - - function sendProgress($rand,$total,$diz) - { - if($this->progress_units <40 && ($rand != $total)) - { - $this->progress_units++; - return; - } - else - { - $this->progress_units = 0; - } - - $inc = round(($rand / $total) * 100); - - if($inc == 0) - { - return; - } - - - - - echo "
-
"; - - $active = "active"; - - if($inc >= 100) - { - $inc = 100; - $active = ""; - } - - echo e107::getForm()->progressBar('inspector',$inc); - - /* echo '
-
-
';*/ - - - echo "
-
"; - - return; - - - // exit; - /* - echo "
- -
"; - */ - /* - - echo "
".$diz."
"; - - - if($total > 0) - { - echo "
".$inc ."%
"; - } - - echo "
- "; - */ - } - - - function exploit_interface() - { - // global $ns; - $ns = e107::getRender(); - - $query = http_build_query($_POST); - - $text = " - - - - "; - $ns -> tablerender(FR_LAN_1, $text); - } - - - function headerCss() - { - $pref = e107::getPref(); - - echo "\n"; - $e_js = e107::getJs(); - - // Core CSS - XXX awaiting for path changes - if (!isset($no_core_css) || !$no_core_css) - { - //echo "\n"; - $e_js->otherCSS('{e_WEB_CSS}e107.css'); - } - - - - if (!deftrue('e_IFRAME') && isset($pref['admincss']) && $pref['admincss']) - { - $css_file = file_exists(THEME.'admin_'.$pref['admincss']) ? 'admin_'.$pref['admincss'] : $pref['admincss']; - //echo "\n"; - $e_js->themeCSS($css_file); - } - elseif (isset($pref['themecss']) && $pref['themecss']) - { - $css_file = file_exists(THEME.'admin_'.$pref['themecss']) ? 'admin_'.$pref['themecss'] : $pref['themecss']; - //echo "\n"; - $e_js->themeCSS($css_file); - } - else - { - $css_file = file_exists(THEME.'admin_style.css') ? 'admin_style.css' : 'style.css'; - //echo "\n"; - $e_js->themeCSS($css_file); - } - - - $e_js->renderJs('other_css', false, 'css', false); - echo "\n\n"; - - // Core CSS - $e_js->renderJs('core_css', false, 'css', false); - echo "\n\n"; - - // Plugin CSS - $e_js->renderJs('plugin_css', false, 'css', false); - echo "\n\n"; - - // Theme CSS - //echo "\n"; - $e_js->renderJs('theme_css', false, 'css', false); - echo "\n\n"; - - // Inline CSS - not sure if this should stay at all! - $e_js->renderJs('inline_css', false, 'css', false); - echo "\n\n"; - - - /* - echo "\n"; - if (strpos(e_SELF.'?'.e_QUERY, 'menus.php?configure') === FALSE && isset($pref['admincss']) && $pref['admincss'] && file_exists(THEME.$pref['admincss'])) { - $css_file = file_exists(THEME.'admin_'.$pref['admincss']) ? THEME_ABS.'admin_'.$pref['admincss'] : THEME_ABS.$pref['admincss']; - echo "\n"; - } else if (isset($pref['themecss']) && $pref['themecss'] && file_exists(THEME.$pref['themecss'])) - { - $css_file = file_exists(THEME.'admin_'.$pref['themecss']) ? THEME_ABS.'admin_'.$pref['themecss'] : THEME_ABS.$pref['themecss']; - echo "\n"; - - - } - else - { - $css_file = file_exists(THEME.'admin_style.css') ? THEME_ABS.'admin_style.css' : THEME_ABS.'style.css'; - echo "\n"; - } - if (!isset($no_core_css) || !$no_core_css) { - echo "\n"; - } - * */ - - } - - - - -} - -function fileinspector_adminmenu() //FIXME - has problems when navigation is on the LEFT instead of the right. -{ - $var['setup']['text'] = FC_LAN_11; - $var['setup']['link'] = e_SELF."?mode=setup"; - - $var['run']['text'] = FR_LAN_2; - $var['run']['link'] = e_SELF."?mode=run"; - - $icon = e107::getParser()->toIcon('e-fileinspector-24'); - $caption = $icon."".FC_LAN_1.""; - - e107::getNav()->admin($caption, $_GET['mode'], $var); -} - -function e_help() -{ - -// $fi = new file_inspector; - $fi = e107::getSingleton('file_inspector'); - $list = $fi->getLegend(); - - $text = ''; - foreach($list as $v) - { - if(!empty($v[1])) - { - $text .= "
".$v[0]." ".$v[1]."
"; - } - - } - - return array('caption'=>FC_LAN_37, 'text'=>$text); - -} - - - - -require_once(e_ADMIN.'footer.php'); - -function headerjs() -{ - /*$c = e_IMAGE_ABS . 'fileinspector/contract.png'; - $e = e_IMAGE_ABS . 'fileinspector/expand.png'; - - $text = '';*/ - -/* - * // Start of rework -e107::js('footer-inline', " - -c = new Image(); -c = '".SITEURLBASE.e_IMAGE_ABS."fileinspector/contract.png'; -e = '".SITEURLBASE.e_IMAGE_ABS."fileinspector/expand.png'; - -function ec(ecid) { - icon = $('#e_' + ecid).src; - if (icon == e) { - $('#e_' + ecid).src = c; - } else { - $('#e_' + ecid).src = e; - } - div = $('#d_' + ecid).style; - if (div.display == 'none') - { - div.display = ''; - } - else - { - div.display = 'none'; - } -} - -var hideid = 'initial'; -function sh(showid) -{ - if (hideid != showid) - { - show = $('#'+showid).style; - hide = $('#'+hideid).style; - show.display = ''; - hide.display = 'none'; - hideid = showid; - } -} - - - - -");*/ - - -global $e107; -$text = ""; - -$text .= " -\n"; - -return $text; -} - -?> +debug = FALSE; +//require_once(e_HANDLER.'form_handler.php'); +$DOCS_DIRECTORY = $HELP_DIRECTORY; // Give a sensible, albeit probably invalid, value +if (substr($HELP_DIRECTORY,-5,5) == 'help/') +{ + $DOCS_DIRECTORY = substr($HELP_DIRECTORY,0,-5); // Whatever $HELP_DIRECTORY is set to, assume docs are in a subdirectory called 'help' off it +} +$maindirs = array('admin' => $ADMIN_DIRECTORY, 'files' => $FILES_DIRECTORY, 'images' => $IMAGES_DIRECTORY, 'themes' => $THEMES_DIRECTORY, 'plugins' => $PLUGINS_DIRECTORY, 'handlers' => $HANDLERS_DIRECTORY, 'languages' => $LANGUAGES_DIRECTORY, 'downloads' => $DOWNLOADS_DIRECTORY, 'docs' => $DOCS_DIRECTORY); +foreach ($maindirs as $maindirs_key => $maindirs_value) { + $coredir[$maindirs_key] = substr($maindirs_value, 0, -1); +} + +require_once('core_image.php'); + +//$rs = new form; +set_time_limit(18000); +$e_sub_cat = 'fileinspector'; + + +if(isset($_GET['scan'])) +{ + + session_write_close(); + while (@ob_end_clean()); + + + //header("Content-type: text/html; charset=".CHARSET, true); + //$css_file = file_exists(e_THEME.$pref['admintheme'].'/'.$pref['admincss']) ? e_THEME.$pref['admintheme'].'/'.$pref['admincss'] : e_THEME.$pref['admintheme'].'/'.$pref['admincss']; +// $fi = new file_inspector; + + $fi = e107::getSingleton('file_inspector'); + + + echo " + + + Results + + ".$fi->headerCss()." ".headerjs()." + \n"; + +// define('e_IFRAME', true); +// require_once(e_ADMIN."auth.php"); + + + + + + // echo "
loading.."; + + // echo ".."; + //flush(); + + $_POST = $_GET; + + if(vartrue($_GET['exploit'])) + { + $fi->exploit(); + } + else + { + $fi->scan_results(); + } + +// require_once(e_ADMIN."footer.php"); + + echo ""; + + exit(); + +} +else +{ + // $fi = new file_inspector; + $fi = e107::getSingleton('file_inspector'); + + + + + + require_once(e_ADMIN.'auth.php'); + + +// if (e_QUERY) { + // $fi -> snapshot_interface(); + //} + + if (varset($_POST['scan'])) + { + $fi->exploit_interface(); + $fi->scan_config(); + } + elseif($_GET['mode'] == 'run') + { + $mes = e107::getMessage(); + $mes->addInfo(FR_LAN_32);//Run a Scan first + echo $mes->render(); + } + else + { + $fi->scan_config(); + } +} + + + + +class file_inspector { + + var $root_dir; + var $files = array(); + var $parent; + var $count = array(); + var $results = 0; + var $totalFiles = 0; + var $coredir = array(); + var $progress_units = 0; + private $langs = array(); + private $lang_short = array(); + + + private $excludeFiles = array( '.', '..','/','.svn', 'CVS' ,'Thumbs.db', '.git'); + + private $knownSecurityIssues = array('htmlarea', 'e107_docs/docs.php'); +// private $icon = array(); + private $iconTag = array(); + + private $options = array( + 'core' => '', + 'type' =>'list', + 'missing' => 0, + 'noncore' => 9, + 'nolang' => 1, + 'oldcore' => 0, + 'integrity' => 1, + 'regex' => 0, + 'mod' => '', + 'num' => 0, + 'line' => 0 + ); + + + function setOptions($post) + { + foreach($this->options as $k=>$v) + { + if(isset($post[$k])) + { + $this->options[$k] = $post[$k]; + } + } + + } + + + function __construct() + { + + $lng = e107::getLanguage(); + $langs = $lng->installed(); + + if(isset($_GET['scan'])) + { + $this->setOptions($_GET); + } + + $lang_short = array(); + foreach($langs as $k=>$val) + { + if($val == "English") // Core release language, so ignore it. + { + unset($langs[$k]); + continue; + } + + $lang_short[] = $lng->convert($val); + } + + $this->langs = $langs; + $this->lang_short = $lang_short; + + + //TODO LAN + + $this->glyph = array( + 'folder_close' => array(''), + 'folder_up' => array(''), + 'folder_root' => array(''), + + 'warning' => array(''), + 'info' => array(''), + 'fileinspector' => array(''), + + 'folder' => array(''), + 'folder_check' => array('', FC_LAN_24 ), + 'folder_fail' => array('', FC_LAN_25 ), + 'folder_missing' => array('', FC_LAN_26 ), + 'folder_warning' => array(''), + 'folder_old' => array('', FC_LAN_27 ), + 'folder_old_dir' => array(''), + 'folder_unknown' => array('', FC_LAN_28 ), + + 'file_check' => array('', FC_LAN_29), + 'file_core' => array('', FC_LAN_30), + 'file_fail' => array('', FC_LAN_31 ), + 'file_missing' => array('', FC_LAN_32 ), + 'file_old' => array('', FC_LAN_33 ), + 'file_uncalc' => array('', FC_LAN_34 ), + 'file_warning' => array('', FC_LAN_35 ), + 'file_unknown' => array('', FC_LAN_36 ), + + + + ); + + foreach($this->glyph as $k=>$v) + { + + $this->iconTag[$k] = $this->glyph[$k][0]; + + } + + + global $e107,$core_image; + + //$this->totalFiles = count($core_image,COUNT_RECURSIVE); + $this->countFiles($core_image); + + $this -> root_dir = $e107 -> file_path; + if (substr($this -> root_dir, -1) == '/') + { + $this -> root_dir = substr($this -> root_dir, 0, -1); + } + + if ($_POST['core'] == 'fail') + { + $_POST['integrity'] = TRUE; + } + + if (MAGIC_QUOTES_GPC && vartrue($_POST['regex'])) + { + $_POST['regex'] = stripslashes($_POST['regex']); + } + + if ($_POST['regex']) { + if ($_POST['core'] == 'fail') { + $_POST['core'] = 'all'; + } + $_POST['missing'] = 0; + $_POST['integrity'] = 0; + } + } + + + private function opt($key) + { + return $this->options[$key]; + } + + + // Find the Total number of core files before scanning begins. + function countFiles($array) + { + foreach($array as $k=>$val) + { + if(is_array($val)) + { + $this->countFiles($val); + } + elseif($val) + { + $this->totalFiles++; + } + + } + } + + + private function getDiz($key) + { + if(!empty($this->glyph[$key][1])) + { + return $this->glyph[$key][1]; + } + + return $key; + + } + + + public function getLegend() + { + return $this->glyph; + + } + + + function renderHelp() + { + + $text = ""; + foreach($this->iconTag as $k=>$v) + { + $text .= ""; + + } + $text .= "
".$v."".$k."
"; + // echo $text; + } + + + function scan_config() + { + + $frm = e107::getForm(); + $ns = e107::getRender(); + $pref = e107::pref('core'); + + + + + if($_GET['mode'] == 'run') + { + return; + } + + + $tab = array(); + + $head = "
+
"; + + $text = " + "; + + /* $text .= " + + + ";*/ + + $coreOpts = array('full'=>FC_LAN_6, 'all'=>LAN_ALL, 'none'=> LAN_NONE); + + $text .= " + + + "; + + + $dispOpt = array('tree'=>FC_LAN_15, 'list'=>LAN_LIST); + $text .= " + + + + "; + + + + $text .= " + + + "; + + $text .= " + + + "; + + $text .= " + + + "; + + + + + $text .= " + + "; + + $text .= "
".LAN_OPTIONS."
+ ".LAN_SHOW." ".FC_LAN_5.": + ".$frm->select('core',$coreOpts,$_POST['core'])."
+ ".FC_LAN_14.": + ".$frm->select('type', $dispOpt, $_POST['type'])."
+ ".LAN_SHOW." ".FC_LAN_13.": + + ".LAN_YES."   + ".LAN_NO."   +
+ ".LAN_SHOW." ".FC_LAN_7.": + + ".LAN_YES."   + ".LAN_NO."   + ".FC_LAN_23."   +
+ ".LAN_SHOW." ".FC_LAN_21.": + + ".LAN_YES."   + ".LAN_NO."   +
+ ".FC_LAN_8.": + + ".LAN_YES."   + ".LAN_NO."   +
"; + + $tab['basic'] = array('caption'=>LAN_OPTIONS, 'text'=>$text); + + + if ($pref['developer']) { + + $text2 = ""; + /* $text2 .= " + + ";*/ + + $text2 .= " + + + "; + + $text2 .= " + + + "; + + $text2 .= " + + + "; + + $text2 .= " +
".FC_LAN_17."
+ ".FC_LAN_18.": + + ## +
+ ".FC_LAN_19.": + + +
+ ".FC_LAN_20.": + + +
"; + + $tab['advanced'] = array('caption'=>FC_LAN_17, 'text'=>$text2); + } + + + $tabText = e107::getForm()->tabs($tab); + + + + + + $foot = " +
+ ".$frm->admin_button('scan', LAN_GO, 'other')." +
+
+
"; + + $text = $head.$tabText.$foot; + + $ns -> tablerender(FC_LAN_1, $text); + + } + + function scan($dir, $image) + { + + + $handle = opendir($dir.'/'); + while (false !== ($readdir = readdir($handle))) + { + + if ($readdir != '.' && $readdir != '..' && $readdir != '/' && $readdir != 'CVS' && $readdir != 'Thumbs.db' && (strpos('._', $readdir) === FALSE)) + { + $path = $dir.'/'.$readdir; + if (is_dir($path)) + { + $dirs[$path] = $readdir; + } + elseif (!isset($image[$readdir])) + { + $files[$readdir] = $this -> checksum($path, TRUE); + } + } + } + closedir($handle); + + if (isset($dirs)) { + ksort ($dirs); + foreach ($dirs as $dir_path => $dir_list) { + $list[$dir_list] = ($set = $this -> scan($dir_path, $image[$dir_list])) ? $set : array(); + } + } + + if (isset($files)) { + ksort ($files); + foreach ($files as $file_name => $file_list) { + $list[$file_name] = $file_list; + } + } + + return $list; + } + + // Given a full path and filename, looks it up in the list to determine valid actions; returns: + // 'check' - file is expected to be present, and validity is to be checked + // 'ignore' - file may or may not be present - check its validity if found, but not an error if missing + // 'uncalc' - file must be present, but its integrity cannot be checked. + // 'nocalc' - file may be present, but its integrity cannot be checked. Not an error if missing + function check_action($dir, $name) + { + global $coredir; + + if ($name == 'e_inspect.php') { return 'nocalc'; } // Special case for plugin integrity checking + + $filename = $dir.'/'.$name; + $admin_dir = $this->root_dir.'/'.$coredir['admin'].'/'; + $image_dir = $this->root_dir.'/'.$coredir['images'].'/'; + $test_list = array(); + + // Files that are unable to be checked + $test_list[$admin_dir.'core_image.php'] = 'uncalc'; + $test_list[$this->root_dir.'/e107_config.php'] = 'uncalc'; + + // Files that are likely to be renamed by user + $test_list[$admin_dir.'filetypes_.php'] = 'ignore'; + $test_list[$this->root_dir.'/e107.htaccess'] = 'ignore'; + $test_list[$this->root_dir.'/e107.robots.txt'] = 'ignore'; + + if (isset($test_list[$filename])) { return $test_list[$filename]; } + return 'check'; + } + + + // This function does the real work + // $list - + // $deprecated + // $level + // $dir + // &$tree_end + // &$parent_expand + function inspect($list, $deprecated, $level, $dir, &$tree_end = null, &$parent_expand = null) + { + global $coredir; + + $sub_text = ''; + $langs = $this->langs; + $lang_short = $this->lang_short; + + + unset ($childOut); + $parent_expand = false; + if (substr($dir, -1) == '/') + { + $dir = substr($dir, 0, -1); + } + $dir_id = dechex(crc32($dir)); + $this -> files[$dir_id]['.']['level'] = $level; + $this -> files[$dir_id]['.']['parent'] = $this -> parent; + $this -> files[$dir_id]['.']['file'] = $dir; + $directory = $level ? basename($dir) : SITENAME; + $level++; + + // + + + + $this->sendProgress(vartrue($this->count['core']['num']),$this->totalFiles,FR_LAN_1); + + foreach ($list as $key => $value) + { + // $dir_icon = 'fileinspector'; // default as unknown + $this -> parent = $dir_id; + if (is_array($value)) + { // Entry is a subdirectory - recurse another level + $path = $dir.'/'.$key; + $child_open = false; + $child_end = true; + $dir_icon = 'folder_check'; + $sub_text .= $this -> inspect($value, $deprecated[$key], $level, $path, $child_end, $child_expand); + $tree_end = false; + if ($child_expand) + { + $parent_expand = true; + $last_expand = true; + } + } + else + { + $this->sendProgress(vartrue($this->count['core']['num']),$this->totalFiles,FR_LAN_1); + $path = $dir.'/'.$key; + + $fid = strtolower($key); + $this -> files[$dir_id][$fid]['file'] = ($_POST['type'] == 'tree') ? $key : $path; + + if (($this -> files[$dir_id][$fid]['size'] = filesize($path)) !== false) + { // We're checking a file here + if ($this->opt('core') != 'none') + { // Look at core files + $this -> count['core']['num']++; + $this -> count['core']['size'] += $this -> files[$dir_id][$fid]['size']; + + if ($_POST['regex']) // Developer prefs activated - search file contents according to regex + { // TODO Max out of Memory when used + $file_content = file($path); // Get contents of file + + if (($this -> files[$dir_id][$fid]['size'] = filesize($path)) !== FALSE) + { + if ($this -> files[$dir_id][$fid]['lines'] = preg_grep("#".$_POST['regex']."#".$_POST['mod'], $file_content)) + { // Search string found - add file to list + $this -> files[$dir_id][$fid]['file'] = ($_POST['type'] == 'tree') ? $key : $path; + $this -> files[$dir_id][$fid]['icon'] = 'file_core'; + $dir_icon = 'fileinspector'; + $parent_expand = TRUE; + $this -> results++; + } + else + { // Search string not found - discard from list + unset($this -> files[$dir_id][$fid]); + $known[$dir_id][$fid] = true; + $dir_icon = ($dir_icon == 'fileinspector') ? 'folder_unknown': $dir_icon ; + } + } + } + else + { + if ($this->opt('integrity')) + { // Actually check file integrity + switch ($this_action = $this->check_action($dir,$key)) + { + case 'ignore' : + case 'check' : + if ($this->checksum($path) != $value) + { + $this -> count['fail']['num']++; + $this -> count['fail']['size'] += $this -> files[$dir_id][$fid]['size']; + $this -> files[$dir_id][$fid]['icon'] = 'file_fail'; + $dir_icon = 'folder_fail'; + $parent_expand = TRUE; + } + else + { + $this -> count['pass']['num']++; + $this -> count['pass']['size'] += $this -> files[$dir_id][$fid]['size']; + + if ($this->opt('core') != 'fail') + { + $this -> files[$dir_id][$fid]['icon'] = 'file_check'; + $dir_icon = ($dir_icon == 'folder_fail' || $dir_icon == 'folder_missing') ? $dir_icon : 'folder_check'; + } + else + { + unset($this -> files[$dir_id][$fid]); + $known[$dir_id][$fid] = true; + + } + } + break; + case 'uncalc' : + case 'nocalc' : + $this -> count['uncalculable']['num']++; + $this -> count['uncalculable']['size'] += $this -> files[$dir_id][$fid]['size']; + if ($this->opt('core') != 'fail') + { + $this -> files[$dir_id][$fid]['icon'] = 'file_uncalc'; + + } + else + { + unset($this -> files[$dir_id][$fid]); + $known[$dir_id][$fid] = true; + } + break; + } + } + else + { // Just identify as core file + $this -> files[$dir_id][$fid]['icon'] = 'file_core'; + } + } + } + else + { + unset ($this -> files[$dir_id][$fid]); + $known[$dir_id][$fid] = true; + } + } + else if ($this->opt('missing')) + { + switch ($this_action = $this->check_action($dir,$key)) + { + case 'check' : + case 'uncalc' : + $this -> count['missing']['num']++; + $this -> files[$dir_id][$fid]['icon'] = 'file_missing'; + $dir_icon = ($dir_icon == 'folder_fail') ? $dir_icon : 'folder_missing'; + $parent_expand = TRUE; + break; + case 'ignore' : + case 'nocalc' : + // These files can be missing without error - delete from the list + unset ($this -> files[$dir_id][$fid]); + $known[$dir_id][$fid] = true; + break; + } + } + else + { + unset ($this -> files[$dir_id][$fid]); + } + } + } + + if ($this->opt('noncore') || $this->opt('oldcore')) + { + + + + if(!$handle = opendir($dir.'/')) + { + //e107::getMessage()->addInfo("Couldn't Open : ".$dir); + } + + while (is_resource($handle) && false !== ($readdir = readdir($handle))) + { + // $prog_count = $this->count['unknown']['num'] + $this->count['deprecated']['num']; + // $this->sendProgress($prog_count,$this->totalFiles,FR_LAN_1); + + if (!in_array($readdir,$this->excludeFiles) && (strpos('._', $readdir) === false)) + { + + if (is_dir($dir.'/'.$readdir)) + { + if (!isset($list[$readdir]) && ($level > 1 || $readdir == 'e107_install')) + { + $child_open = false; + $child_end = true; + $sub_text .= $this->inspect(array(), $deprecated[$readdir], $level, $dir.'/'.$readdir, $child_end, $child_expand); + $tree_end = false; + if ($child_expand) + { + $parent_expand = true; + $last_expand = true; + } + } + + + } + else + { + + + + if($this->opt('nolang') && !empty($langs) && !empty($lang_short)) // Hide Non-core Languages. + { + + // PHP Lang files. + $lreg = "/[\/_](".implode("|",$langs).")/"; + if(preg_match($lreg, $dir.'/'.$readdir)) + { + continue; + } + + // TinyMce Lang files. + $lregs = "/[\/_](".implode("|",$lang_short).")_dlg\.js/"; + if(preg_match($lregs, $dir.'/'.$readdir)) + { + continue; + } + + // PhpMailer Lang Files. + $lregsm = "/[\/_]phpmailer\.lang-(".implode("|",$lang_short).")\.php/"; + if(preg_match($lregsm, $dir.'/'.$readdir)) + { + continue; + } + } + + $aid = strtolower($readdir); + + if (!isset($this -> files[$dir_id][$aid]['file']) && !$known[$dir_id][$aid]) + { + if ($this->checkKnownSecurity($dir.'/'.$readdir) === false) + { + if (isset($deprecated[$readdir])) + { + if ($this->opt('oldcore')) + { + $this -> files[$dir_id][$aid]['file'] = ($_POST['type'] == 'tree') ? $readdir : $dir.'/'.$readdir; + $this -> files[$dir_id][$aid]['size'] = filesize($dir.'/'.$readdir); + $this -> files[$dir_id][$aid]['icon'] = 'file_old'; + $this -> count['deprecated']['num']++; + $this -> count['deprecated']['size'] += $this -> files[$dir_id][$aid]['size']; + $dir_icon = 'folder_old'; + } + } + else + { + if ($this->opt('noncore')) + { + $this -> files[$dir_id][$aid]['file'] = ($_POST['type'] == 'tree') ? $readdir : $dir.'/'.$readdir; + $this -> files[$dir_id][$aid]['size'] = filesize($dir.'/'.$readdir); + //echo "
dir: ".$dir.'/'.$readdir. " ( ".$this -> files[$dir_id][$aid]['size'].")"; + $this -> files[$dir_id][$aid]['icon'] = 'file_unknown'; + $this -> count['unknown']['num']++; + $this -> count['unknown']['size'] += $this -> files[$dir_id][$aid]['size']; + } + } + } + else + { + $this -> files[$dir_id][$aid]['file'] = ($_POST['type'] == 'tree') ? $readdir : $dir.'/'.$readdir; + $this -> files[$dir_id][$aid]['size'] = filesize($dir.'/'.$readdir); + $this -> files[$dir_id][$aid]['icon'] = 'file_warning'; + $this -> count['warning']['num']++; + $this -> count['warning']['size'] += $this -> files[$dir_id][$aid]['size']; + $this -> count['deprecated']['num']++; + $this -> count['deprecated']['size'] += $this -> files[$dir_id][$aid]['size']; + $dir_icon = 'folder_warning'; + $parent_expand = TRUE; + } + + $regexOpt = $this->opt('regex'); + if (!empty($regexOpt)) + { + $file_content = file($dir.'/'.$readdir); + if ($this -> files[$dir_id][$aid]['lines'] = preg_grep("#".$_POST['regex']."#".$_POST['mod'], $file_content)) + { + $dir_icon = 'fileinspector'; + $parent_expand = TRUE; + $this -> results++; + } + else + { + unset($this -> files[$dir_id][$aid]); + $dir_icon = ($dir_icon == 'fileinspector') ? $dir_icon : 'folder'; + } + } + else + { + if (isset($deprecated[$readdir])) + { + if ($this->opt('oldcore')) + { + $dir_icon = ($dir_icon == 'folder_warning' || $dir_icon == 'folder_fail' || $dir_icon == 'folder_missing' ) ? $dir_icon : 'folder_old'; + $parent_expand = TRUE; + } + } + else + { + if ($this->opt('noncore')) + { + $dir_icon = ($dir_icon == 'folder_warning' || $dir_icon == 'folder_fail' || $dir_icon == 'folder_missing' || $dir_icon == 'folder_old' || $dir_icon == 'folder_old_dir') ? $dir_icon : 'folder_unknown'; + $parent_expand = TRUE; + } + } + } + } else if ($this->opt('core') == 'none') { + unset($this -> files[$dir_id][$aid]); + } + } + } + } + closedir($handle); + + } + + $this->sendProgress($this->count['core']['num'],$this->totalFiles,FR_LAN_1); + + $dir_icon = $dir_icon ? $dir_icon : 'folder_unknown'; + // $icon = ""; + + $icon = $this->iconTag[$dir_icon]; + + $tp = e107::getParser(); + + $imgBlank = $tp->toImage('{e_IMAGE}fileinspector/blank.png', array( + 'alt' => '', + 'legacy' => '{e_IMAGE}fileinspector/', + 'w' => 9, + 'h' => 9, + 'class' => 'c', + )); + + $imgExpand = $tp->toImage('{e_IMAGE}fileinspector/expand.png', array( + 'alt' => '', + 'legacy' => '{e_IMAGE}fileinspector/', + 'w' => 15, + 'class' => 'e', + 'id' => 'e_' . $dir_id, + )); + + $imgContract = $tp->toImage('{e_IMAGE}fileinspector/contract.png', array( + 'alt' => '', + 'legacy' => '{e_IMAGE}fileinspector/', + 'w' => 15, + 'class' => 'e', + 'id' => 'e_' . $dir_id, + )); + + $hide = ($last_expand && $dir_icon != 'folder_core') ? "" : "style='display: none'"; + + $text = '
'; + $text .= $tree_end ? $imgBlank : '' . ($hide ? $imgExpand : $imgContract) . ''; + $text .= ' ' . $icon . ' ' . $directory . ''; + $text .= $tree_end ? '' : '
' . $sub_text . '
'; + $text .= '
'; + + $this -> files[$dir_id]['.']['icon'] = $dir_icon; + + return $text; + } + + private function checkKnownSecurity($path) + { + + foreach($this->knownSecurityIssues as $v) + { + if(strpos($path, $v) !== false) + { + return true; + } + } + + return false; + } + + + + function scan_results() + { + global $ns, $rs, $core_image, $deprecated_image; + $scan_text = $this -> inspect($core_image, $deprecated_image, 0, $this -> root_dir); + + + $this->sendProgress($this->totalFiles,$this->totalFiles,'      '); + + echo "
 
"; + + if ($this->opt('type') == 'tree') + { + $text = "
+ + + + "; + + $text .= ""; + + $text .= " + + "; + + $text .= "
".FR_LAN_2."
+
+ ".$scan_text." +
+
"; + } + else + { + $text = "
+ + + + "; + + $text .= " + + +
".FR_LAN_2."
"; + } + + $text .= ""; + + if ($this->opt('type') == 'tree') + { + $text .= " + "; + } + else + { + $text .= ""; + } + + if ($this->opt('core') != 'none') + { + $text .= " + "; + } + if ($this->opt('missing')) + { + $text .= ""; + } + if ($this->opt('noncore')) + { + $text .= ""; + } + if ($this->opt('oldcore')) + { + $text .= ""; + } + if ($this->opt('core') == 'all') + { + $text .= ""; + } + + if ($this -> count['warning']['num']) + { + $text .= ""; + $text .= ""; + + $text .= ""; + + $text .= ""; + + } + if ($this->opt('integrity') && ($this->opt('core') != 'none')) + { + $integrity_icon = $this -> count['fail']['num'] ? 'integrity_fail.png' : 'integrity_pass.png'; + $integrity_text = $this -> count['fail']['num'] ? '( '.$this -> count['fail']['num'].' '.FR_LAN_19.' )' : '( '.FR_LAN_20.' )'; + $text .= ""; + $text .= ""; + + $text .= ""; + $text .= ""; + $text .= ""; + + $text .= ""; + + $text .= ""; + + $text .= ""; + } + + if ($this->opt('type') == 'tree' && !$this -> results && $this->opt('regex')) + { + $text .= " + "; + } + + $text .= "
".FR_LAN_3." root_dir))."')\"> +
".FR_LAN_3."
".$this->iconTag['file_core']." ".FC_LAN_5.": ".($this -> count['core']['num'] ? $this -> count['core']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['core']['size'], 2)."
".$this->iconTag['file_missing']." ".FC_LAN_13.": ".($this -> count['missing']['num'] ? $this -> count['missing']['num'] : LAN_NONE)." 
".$this->iconTag['file_unknown']." ".FC_LAN_7.": ".($this -> count['unknown']['num'] ? $this -> count['unknown']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['unknown']['size'], 2)."
".$this->iconTag['file_old']." ".FR_LAN_24.": ".($this -> count['deprecated']['num'] ? $this -> count['deprecated']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['deprecated']['size'], 2)."
".$this->iconTag['file']." ".FR_LAN_6.": ".($this -> count['core']['num'] + $this -> count['unknown']['num'] + $this -> count['deprecated']['num'])." ".$this -> parsesize($this -> count['core']['size'] + $this -> count['unknown']['size'] + $this -> count['deprecated']['size'], 2)."
 
+ ".$this->iconTag['warning']." ".FR_LAN_26."
".$this->iconTag['file_warning']." ".FR_LAN_28.": ".($this -> count['warning']['num'] ? $this -> count['warning']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['warning']['size'], 2)."
".FR_LAN_27."
 
".FR_LAN_7." ".$integrity_text."
".$this->iconTag['file_check']." ".FR_LAN_8.": ".($this -> count['pass']['num'] ? $this -> count['pass']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['pass']['size'], 2)."
".$this->iconTag['file_fail']." ".FR_LAN_9.": ".($this -> count['fail']['num'] ? $this -> count['fail']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['fail']['size'], 2)."
".$this->iconTag['file_uncalc']." ".FR_LAN_25.": ".($this -> count['uncalculable']['num'] ? $this -> count['uncalculable']['num'] : LAN_NONE)." ".$this -> parsesize($this -> count['uncalculable']['size'], 2)."
 
".$this->iconTag['info']." ".FR_LAN_10.": 
+ +

".FR_LAN_23."
"; + + if ($this->opt('type') != 'tree') + { + $text .= "
+ "; + if (!$this -> results && $this->opt('regex')) + { + $text .= ""; + } + + + // print_a($this -> files); + } + + + + + foreach ($this -> files as $dir_id => $fid) + { + + // $this->sendProgress($cnt,$this->totalFiles,$path); + + ksort($fid); + $text .= ($this->opt('type') == 'tree') ? "
".FR_LAN_23."
" : ""; + $initial = FALSE; + foreach ($fid as $key => $stext) + { + + // print_a($stext); + + $iconKey = $stext['icon']; + + if (!$initial) + { + if ($this->opt('type') == 'tree') + { + + $rootIconKey = ($stext['level'] ? "folder_up" : "folder_root"); + + $text .= " + "; + } + } + else + { + if ($this->opt('type') != 'tree') + { + $stext['file'] = str_replace($this -> root_dir."/", "", $stext['file']); + } + + $text .= $this->renderRow($stext); + + + } + $initial = TRUE; + } + $text .= ($this->opt('type') == 'tree') ? "" : ""; + } + + if ($this->opt('type') != 'tree') { + $text .= "
"; + } + + $text .= "
+
"; + + echo e107::getMessage()->render(); + echo $text; + + + //$ns -> tablerender(FR_LAN_1.'...', $text); + + } + + + + + function renderRow($stext) + { + + $mode = $this->opt('core'); + + $iconKey = $stext['icon']; + + // return "".$mode." ( ".$iconKey.")"; + + + if($mode == 'full' && $iconKey == 'file_check' ) + { + return ''; + } + + if($mode == 'none') + { + // return ''; + } + + + $text = ''; + $text .= " + + getDiz($iconKey)."\">".$this->iconTag[$iconKey]." ".$stext['file']." "; + + if ($this->opt('regex')) + { + if ($this->opt('num') || $this->opt('line')) + { + $text .= "
"; + } + + foreach ($stext['lines'] as $rkey => $rvalue) + { + if ($this->opt('num')) + { + $text .= "[".($rkey + 1)."] "; + } + + if ($this->opt('line')) + { + $text .= htmlspecialchars($rvalue)."
"; + } + } + + $text .= "
"; + } + else + { + $text .= " + ".$this -> parsesize($stext['size']); + } + + $text .= ""; + + return $text; + } + + + + + + + + + + function create_image($dir) { + global $core_image, $deprecated_image,$coredir; + + foreach ($coredir as $trim_key => $trim_dirs) { + $search[$trim_key] = "'".$trim_dirs."'"; + $replace[$trim_key] = "\$coredir['".$trim_key."']"; + } + + $data = " scan($dir) : $core_image; + $image_array = var_export($scan_current, true); + $image_array = str_replace($search, $replace, $image_array); + $data .= "\$core_image = ".$image_array.";\n\n"; + + $scan_deprecated = ($_POST['snaptype'] == 'deprecated') ? $this -> scan($dir, $core_image) : $deprecated_image; + $image_array = var_export($scan_deprecated, true); + $image_array = str_replace($search, $replace, $image_array); + $data .= "\$deprecated_image = ".$image_array.";\n\n"; + + $data .= "?>"; + $fp = fopen(e_ADMIN.'core_image.php', 'w'); + fwrite($fp, $data); + } + + function snapshot_interface() + { + $ns = e107::getRender(); + $frm = e107::getRender(); + $text = ""; + + if (isset($_POST['create_snapshot'])) + { + $this -> create_image($_POST['snapshot_path']); + $text = "
+
+ snapshot_interface + + + "; + + $text .= " + + + + + +
Snapshot Created
+ The snapshot (".e_ADMIN."core_image.php) was successfully created. +
".$frm->admin_button('main_page', 'Return To Main Page', 'submit')."
+
+

"; + } + + $text .= "
+
+ + + + "; + + $text .= " + + + + + + + + + + + +
Create Snapshot
+ Absolute path of root directory to create image from: + + root_dir)."' /> +
+ Create snapshot of current or deprecated core files: + + Current   + Deprecated   +
".$frm->admin_button('create_snapshot', 'Create Snapshot', 'create')."
+
+
"; + + $ns -> tablerender('Snapshot', $text); + + } + + function checksum($filename) + { + $checksum = md5(str_replace(array(chr(13),chr(10)), "", file_get_contents($filename))); + return $checksum; + } + + function parsesize($size, $dec = 0) { + $size = $size ? $size : 0; + $kb = 1024; + $mb = 1024 * $kb; + $gb = 1024 * $mb; + $tb = 1024 * $gb; + if ($size < $kb) { + return $size." ".CORE_LAN_B; + } else if($size < $mb) { + return round($size/$kb)." ".CORE_LAN_KB; + } else if($size < $gb) { + return round($size/$mb, $dec)." ".CORE_LAN_MB; + } else if($size < $tb) { + return round($size/$gb, $dec)." ".CORE_LAN_GB; + } else { + return round($size/$tb, $dec)." ".CORE_LAN_TB; + } + } + + function regex_match($file) { + $file_content = file_get_contents($file); + $match = preg_match($_POST['regex'], $file_content); + + return $match; + } + + + function sendProgress($rand,$total,$diz) + { + if($this->progress_units <40 && ($rand != $total)) + { + $this->progress_units++; + return; + } + else + { + $this->progress_units = 0; + } + + $inc = round(($rand / $total) * 100); + + if($inc == 0) + { + return; + } + + + + + echo "
+
"; + + $active = "active"; + + if($inc >= 100) + { + $inc = 100; + $active = ""; + } + + echo e107::getForm()->progressBar('inspector',$inc); + + /* echo '
+
+
';*/ + + + echo "
+
"; + + return; + + + // exit; + /* + echo "
+ +
"; + */ + /* + + echo "
".$diz."
"; + + + if($total > 0) + { + echo "
".$inc ."%
"; + } + + echo "
+ "; + */ + } + + + function exploit_interface() + { + // global $ns; + $ns = e107::getRender(); + + $query = http_build_query($_POST); + + $text = " + + + + "; + $ns -> tablerender(FR_LAN_1, $text); + } + + + function headerCss() + { + $pref = e107::getPref(); + + echo "\n"; + $e_js = e107::getJs(); + + // Core CSS - XXX awaiting for path changes + if (!isset($no_core_css) || !$no_core_css) + { + //echo "\n"; + $e_js->otherCSS('{e_WEB_CSS}e107.css'); + } + + + + if (!deftrue('e_IFRAME') && isset($pref['admincss']) && $pref['admincss']) + { + $css_file = file_exists(THEME.'admin_'.$pref['admincss']) ? 'admin_'.$pref['admincss'] : $pref['admincss']; + //echo "\n"; + $e_js->themeCSS($css_file); + } + elseif (isset($pref['themecss']) && $pref['themecss']) + { + $css_file = file_exists(THEME.'admin_'.$pref['themecss']) ? 'admin_'.$pref['themecss'] : $pref['themecss']; + //echo "\n"; + $e_js->themeCSS($css_file); + } + else + { + $css_file = file_exists(THEME.'admin_style.css') ? 'admin_style.css' : 'style.css'; + //echo "\n"; + $e_js->themeCSS($css_file); + } + + + $e_js->renderJs('other_css', false, 'css', false); + echo "\n\n"; + + // Core CSS + $e_js->renderJs('core_css', false, 'css', false); + echo "\n\n"; + + // Plugin CSS + $e_js->renderJs('plugin_css', false, 'css', false); + echo "\n\n"; + + // Theme CSS + //echo "\n"; + $e_js->renderJs('theme_css', false, 'css', false); + echo "\n\n"; + + // Inline CSS - not sure if this should stay at all! + $e_js->renderJs('inline_css', false, 'css', false); + echo "\n\n"; + + + /* + echo "\n"; + if (strpos(e_SELF.'?'.e_QUERY, 'menus.php?configure') === FALSE && isset($pref['admincss']) && $pref['admincss'] && file_exists(THEME.$pref['admincss'])) { + $css_file = file_exists(THEME.'admin_'.$pref['admincss']) ? THEME_ABS.'admin_'.$pref['admincss'] : THEME_ABS.$pref['admincss']; + echo "\n"; + } else if (isset($pref['themecss']) && $pref['themecss'] && file_exists(THEME.$pref['themecss'])) + { + $css_file = file_exists(THEME.'admin_'.$pref['themecss']) ? THEME_ABS.'admin_'.$pref['themecss'] : THEME_ABS.$pref['themecss']; + echo "\n"; + + + } + else + { + $css_file = file_exists(THEME.'admin_style.css') ? THEME_ABS.'admin_style.css' : THEME_ABS.'style.css'; + echo "\n"; + } + if (!isset($no_core_css) || !$no_core_css) { + echo "\n"; + } + * */ + + } + + + + +} + +function fileinspector_adminmenu() //FIXME - has problems when navigation is on the LEFT instead of the right. +{ + $var['setup']['text'] = FC_LAN_11; + $var['setup']['link'] = e_SELF."?mode=setup"; + + $var['run']['text'] = FR_LAN_2; + $var['run']['link'] = e_SELF."?mode=run"; + + $icon = e107::getParser()->toIcon('e-fileinspector-24'); + $caption = $icon."".FC_LAN_1.""; + + e107::getNav()->admin($caption, $_GET['mode'], $var); +} + +function e_help() +{ + +// $fi = new file_inspector; + $fi = e107::getSingleton('file_inspector'); + $list = $fi->getLegend(); + + $text = ''; + foreach($list as $v) + { + if(!empty($v[1])) + { + $text .= "
".$v[0]." ".$v[1]."
"; + } + + } + + return array('caption'=>FC_LAN_37, 'text'=>$text); + +} + + + + +require_once(e_ADMIN.'footer.php'); + +function headerjs() +{ + /*$c = e_IMAGE_ABS . 'fileinspector/contract.png'; + $e = e_IMAGE_ABS . 'fileinspector/expand.png'; + + $text = '';*/ + +/* + * // Start of rework +e107::js('footer-inline', " + +c = new Image(); +c = '".SITEURLBASE.e_IMAGE_ABS."fileinspector/contract.png'; +e = '".SITEURLBASE.e_IMAGE_ABS."fileinspector/expand.png'; + +function ec(ecid) { + icon = $('#e_' + ecid).src; + if (icon == e) { + $('#e_' + ecid).src = c; + } else { + $('#e_' + ecid).src = e; + } + div = $('#d_' + ecid).style; + if (div.display == 'none') + { + div.display = ''; + } + else + { + div.display = 'none'; + } +} + +var hideid = 'initial'; +function sh(showid) +{ + if (hideid != showid) + { + show = $('#'+showid).style; + hide = $('#'+hideid).style; + show.display = ''; + hide.display = 'none'; + hideid = showid; + } +} + + + + +");*/ + + +global $e107; +$text = ""; + +$text .= " +\n"; + +return $text; +} + +?> diff --git a/e107_admin/frontpage.php b/e107_admin/frontpage.php index 453ea97d6..ab5acd8c2 100644 --- a/e107_admin/frontpage.php +++ b/e107_admin/frontpage.php @@ -1,754 +1,754 @@ - 'news.php', 'title' => ADLAN_0); // TODO Move to e107_plugins/news - -$front_page['wmessage'] = array('page' => 'index.php', 'title' => ADLAN_28, 'diz'=>'index.php'); - -if($sql->db_Select('page', 'page_id, page_title', "menu_name=''")) // TODO Move to e107_plugins/page -{ - $front_page['custom']['title'] = FRTLAN_30; - while($row = $sql->db_Fetch()) - { - $front_page['custom']['page'][] = array('page' => 'page.php?'.$row['page_id'], 'title' => $row['page_title']); - } -} - -// Now let any plugins add to the options - must append to the $front_page array as above - - - //v2.x spec. ---------- - $new = e107::getAddonConfig('e_frontpage'); - foreach($new as $k=>$v) - { - $front_page[$k] = $v; - } - - // v1.x spec.--------------- - if(!empty($frontPref['e_frontpage_list'])) - { - foreach($frontPref['e_frontpage_list'] as $val) - { - if(is_readable(e_PLUGIN.$val.'/e_frontpage.php')) - { - require_once (e_PLUGIN.$val.'/e_frontpage.php'); - } - } - } - - - -// Make sure links relative to SITEURL -foreach($front_page as &$front_value) -{ - if(is_array($front_value['page'])) - { // Its a URL with multiple options - foreach($front_value['page'] as &$multipage) - { - $multipage = str_replace(e_HTTP, '', $multipage); - //if (substr($multipage, 0, 1) != '/') $multipage = '/'.$multipage; - } - } - else - { - $front_value = str_replace(e_HTTP, '', $front_value); - //if (substr($front_value, 0, 1) != '/') $front_value = '/'.$front_value; - } -} - -// print_a($front_page); - - -// Now sort out list of rules for display (based on $pref data to start with) -$gotpub = FALSE; -if(is_array($frontPref['frontpage'])) -{ - $i = 1; - foreach($frontPref['frontpage'] as $class => $val) - { - if($class == 'all') - { - $class = e_UC_PUBLIC; - $gotpub = TRUE; - } - if($val) - { // Only add non-null pages - $fp_settings[$i] = array('order' => $i, 'class' => $class, 'page' => $val, 'force' => varset($frontPref['frontpage_force'][$class], '')); - $i ++; - } - } -} -else -{ // Legacy stuff to convert - $fp_settings = array(); - $fp_settings[] = array('order' => 0, 'class' => e_UC_PUBLIC, 'page' => varset($frontPref['frontpage'], 'news.php'), 'force' => ''); -} - -if(!$gotpub) -{ // Need a 'default' setting - usually 'all' - $fp_settings[] = array('order' => $i, 'class' => e_UC_PUBLIC, 'page' => (isset($frontPref['frontpage']['all']) ? $frontPref['frontpage']['all'] : 'news.php'), 'force' => ''); -} - -$fp_update_prefs = FALSE; - - -/* -Following code replaced - values not passed on image clicks with Firefox -if(isset($_POST['fp_inc'])) -{ - $mv = intval($_POST['fp_inc']); - echo "Increment: {$mv}
"; - if(($mv > 1) && ($mv <= count($fp_settings))) - { - $temp = $fp_settings[$mv - 1]; - $fp_settings[$mv - 1] = $fp_settings[$mv]; - $fp_settings[$mv] = $temp; - $fp_update_prefs = TRUE; - frontpage_adminlog('01', 'Inc '.$mv); - } -} -elseif(isset($_POST['fp_dec'])) -{ - $mv = intval($_POST['fp_dec']); - echo "Decrement: {$mv}
"; - if(($mv > 0) && ($mv < count($fp_settings))) - { - $temp = $fp_settings[$mv + 1]; - $fp_settings[$mv + 1] = $fp_settings[$mv]; - $fp_settings[$mv] = $temp; - $fp_update_prefs = TRUE; - frontpage_adminlog('01', 'Dec '.$mv); - } -} -*/ - -if (isset($_POST)) -{ - - // avoid endless loop. - if($_POST['frontpage'] == 'other' && (trim($_POST['frontpage_other']) == 'index.php' || trim($_POST['frontpage_other']) == '{e_BASE}index.php')) - { - $_POST['frontpage'] = 'wmessage'; - $_POST['frontpage_other'] = ''; - } - - - foreach ($_POST as $k => $v) - { - $incDec = substr($k, 0, 6); - $idNum = substr($k, 6); - if ($incDec == 'fp_inc') - { - $mv = intval($idNum); - if(($mv > 1) && ($mv <= count($fp_settings))) - { - $temp = $fp_settings[$mv - 1]; - $fp_settings[$mv - 1] = $fp_settings[$mv]; - $fp_settings[$mv] = $temp; - $fp_update_prefs = TRUE; - frontpage_adminlog('01', 'Inc '.$mv); - } - break; - } - elseif ($incDec == 'fp_dec') - { - $mv = intval($idNum); - if(($mv > 0) && ($mv < count($fp_settings))) - { - $temp = $fp_settings[$mv + 1]; - $fp_settings[$mv + 1] = $fp_settings[$mv]; - $fp_settings[$mv] = $temp; - $fp_update_prefs = TRUE; - frontpage_adminlog('01', 'Dec '.$mv); - } - break; - } - } -} - - - -// Edit an existing rule -if(isset($_POST['fp_edit_rule'])) -{ - $_POST['type'] = (isset($_POST['edit']['all'])) ? 'all_users' : 'user_class'; - $_POST['class'] = key($_POST['edit']); -} - -// Cancel Edit - - -if(isset($_POST['fp_save_new'])) -{ // Add or edit an existing rule here. - // fp_order - zero for a new rule, non-zero if editing an existing rule - // class - user class for rule - // frontpage - radio button option indicating type of page (for home page) - // frontpage_multipage[] - the other information for custom pages and similar - array index matches value of 'frontpage' when selected - // frontpage_other - URL for 'other' home page - // fp_force_page - radio button option indicating type of page (for post-login page) - // fp_force_page_multipage[] - the other information for custom pages and similar - array index matches value of 'frontpage' when selected - // fp_force_page_other - URL for forced post-login 'other' page - - - if($_POST['frontpage'] == 'other') - { - $_POST['frontpage_other'] = trim($tp->toForm($_POST['frontpage_other'])); - $frontpage_value = $_POST['frontpage_other'] ? $_POST['frontpage_other'] : 'news.php'; - } - else - { - if(is_array($front_page[$_POST['frontpage']]['page'])) - { - $frontpage_value = $front_page[$_POST['frontpage']]['page'][$_POST['frontpage_multipage'][$_POST['frontpage']]]['page']; - } - else - { - $frontpage_value = $front_page[$_POST['frontpage']]['page']; - } - } - - if($_POST['fp_force_page'] == 'other') - { - $_POST['fp_force_page_other'] = trim($tp->toForm($_POST['fp_force_page_other'])); - $forcepage_value = $_POST['fp_force_page_other']; // A null value is allowable here - } - else - { - if(is_array($front_page[$_POST['fp_force_page']]['page'])) - { - $forcepage_value = $front_page[$_POST['fp_force_page']]['page'][$_POST['fp_force_page_multipage'][$_POST['fp_force_page']]]['page']; - } - else - { - $forcepage_value = $front_page[$_POST['fp_force_page']]['page']; - } - } - - $temp = array('order' => intval($_POST['fp_order']), 'class' => $_POST['class'], 'page' => $frontpage_value, 'force' => trim($forcepage_value)); - - if($temp['order'] == 0) // New index to add - { - $ind = 0; - for($i = 1; $i <= count($fp_settings); $i ++) - { - if($fp_settings[$i]['class'] == $temp['class']) - $ind = $i; - } - - if($ind) - { - $mes->addDebug(print_a($fp_settings,true)); - $mes->addError(FRTLAN_56." ".$ind); - unset($fp_settings[$ind]); // Knock out duplicate definition for class - } - - array_unshift($fp_settings, $temp); // Deliberately add twice - array_unshift($fp_settings, $temp); // ....because re-indexed from zero - unset($fp_settings[0]); // Then knock out index zero - $fp_update_prefs = TRUE; - frontpage_adminlog('02', "class => {$_POST['class']},[!br!]page => {$frontpage_value},[!br!]force => {$forcepage_value}"); - } - elseif(array_key_exists($temp['order'], $fp_settings)) - { - $fp_settings[$temp['order']] = $temp; - $fp_update_prefs = TRUE; - frontpage_adminlog('03', "posn => {$temp},[!br!]class => {$_POST['class']},[!br!]page => {$frontpage_value},[!br!]force => {$forcepage_value}"); - } - else - { // Someone playing games - $mes->addError(FRTLAN_57); - } -} - -if(isset($_POST['fp_delete_rule'])) -{ - if(isset($fp_settings[key($_POST['fp_delete_rule'])])) - { - $rule_no = key($_POST['fp_delete_rule']); - $array_size = count($fp_settings); - frontpage_adminlog('04', "Rule {$rule_no},[!br!]class => {$fp_settings[$rule_no]['class']},[!br!]page => {$fp_settings[$rule_no]['page']},[!br!]force => {$fp_settings[$rule_no]['force']}"); - unset($fp_settings[$rule_no]); - while($rule_no < $array_size) - { // Move up and renumber any entries after the deleted rule - $fp_settings[$rule_no] = $fp_settings[$rule_no + 1]; - $rule_no ++; - unset($fp_settings[$rule_no]); - } - $fp_update_prefs = TRUE; - } -} - -if($fp_update_prefs) -{ // Save the two arrays - $fp_list = array(); - $fp_force = array(); - for($i = 1; $i <= count($fp_settings); $i ++) - { - $fp_list[$fp_settings[$i]['class']] = $fp_settings[$i]['page']; - $fp_force[$fp_settings[$i]['class']] = $fp_settings[$i]['force']; - } - - $corePrefs = e107::getConfig('core'); // Core Prefs Object. - $corePrefs->set('frontpage', $fp_list); - $corePrefs->set('frontpage_force', $fp_force); - $result = $corePrefs->save(FALSE, TRUE); - $mes->addDebug("

Home

".print_a($fp_list, true)); - $mes->addDebug("

Post-Login

".print_a($fp_force, true)); -} - - - - -// All updates complete now - latest data is in the $fp_settings, $fp_list and $fp_force arrays -$fp = new frontpage($front_page); - - - - - -class frontpage -{ - protected $frm; - protected $frontPage = array(); // List of options for front page - - public function __construct($fp) - { - $this->frm = e107::getForm(); - $this->frontPage = $fp; - - $ns = e107::getRender(); - $mes = e107::getMessage(); - - global $fp_settings; - - - if(vartrue($_GET['mode']) == 'create') - { - $text = $this->edit_rule(array('order' => 0, 'class' => e_UC_PUBLIC, 'page' => 'news.php', 'force' => FALSE)); // Display edit form as well - // $text .= $this->select_class($fp_settings, FALSE); - $ns->tablerender(FRTLAN_PAGE_TITLE.SEP.FRTLAN_42, $text); - } - elseif(vartrue($_GET['id'])) - { - $key = intval($_GET['id']); - $text = $this->edit_rule($fp_settings[$key]); // Display edit form as well - // $text .= $this->select_class($fp_settings, FALSE); - $ns->tablerender(FRTLAN_PAGE_TITLE.SEP.FRTLAN_46, $text); - } - else - { // Just show existing rules - $ns->tablerender(FRTLAN_PAGE_TITLE.SEP.FRTLAN_13, $mes->render().$this->select_class($fp_settings, TRUE)); - } - - } - - - - /** - * Show a list of existing rules, with edit/delete/move buttons, and optional button to add a new rule - * - * @param boolean $show_button - show the 'Add new rule' button if true - * - * @return string text for display - */ - function select_class(&$fp_settings, $show_button = TRUE) - { - $frm = e107::getForm(); - // List of current settings - $show_legend = $show_button ? " class='e-hideme'" : ''; - $text = " -
- -
- ".FRTLAN_13." - - - - - - - - - - - - - - - - - - - "; - - foreach($fp_settings as $order => $current_value) - { - $title = e107::getUserClass()->getName($current_value['class']); - $text .= " - - - - - - - "; - - - } - $text .= " - -
".LAN_ORDER."".LAN_USERCLASS."".FRTLAN_49."".FRTLAN_35."".LAN_OPTIONS."
".$order."".$title."".$this->lookup_path($current_value['page'])."".$this->lookup_path($current_value['force'])." -
"; - - // ".$frm->admin_button('fp_inc',$order,'up',ADMIN_UP_ICON)." - // ".$frm->admin_button('fp_dec',$order,'down',ADMIN_DOWN_ICON)." - - $text .= " - ".ADMIN_EDIT_ICON." - ".$frm->admin_button('fp_delete_rule['.$order.']',$order,'',ADMIN_DELETE_ICON)." -
-
"; - - if($show_button) - { - $text .= " - "; - } - - $text .= " -
-
"; - - return $text; - } - - - - /** - * Display form to add/edit rules - * - * @param array $rule_info - initial data (must be preset if new rule) - * - * @return string - text for display - */ - function edit_rule($rule_info) - { - $is_other_home = TRUE; - $is_other_force = TRUE; - //$force_checked = $rule_info['force'] ? " checked='checked'" : ''; - $text_tmp_1 = ''; - $text_tmp_2 = ''; - foreach($this->frontPage as $front_key => $front_value) - { - //$type_selected = FALSE; - - $text_tmp_1 .= " - - ".$this->show_front_val('frontpage', $front_key, $front_value, $is_other_home, $rule_info['page'])." - - "; - - $text_tmp_2 .= " - - ".$this->show_front_val('fp_force_page', $front_key, $front_value, $is_other_force, $rule_info['force'])." - - "; - - } - -// ".($rule_info['order'] ? FRTLAN_46 : FRTLAN_42)." - - $text = " -
- - "; - - $text .= ' - '; - - $text .= " -
-
- - - - - - - - - - - - -
Selection - - - - - - ".$text_tmp_1." - ".$this->add_other('frontpage', $is_other_home, $rule_info['page'])." -
-
-
- -
- - - - - - - - - - - -
- - - - - - ".$text_tmp_2." - ".$this->add_other('fp_force_page', $is_other_force, $rule_info['force'])." -
-
-
-
- - - - - - - - - - - - - -
".FRTLAN_43."".e107::getUserClass()->uc_dropdown('class', $rule_info['class'], 'public,guest,member,admin,main,classes')."
".LAN_ORDER."".$this->frm->number('fp_order', $rule_info['order'], 3, 'min=0')."
- -
- - ".$this->frm->admin_button('fp_save_new', LAN_UPDATE, 'update')." - ".$this->frm->admin_button('fp_cancel', LAN_CANCEL, 'cancel')." -
- -
- "; - return $text; - } - - - - /** - * Given a path string related to a choice, returns the 'type' (title) for it - * - * @param string $path - * - * @return string - title of option - */ - function lookup_path($path) - { - foreach($this->frontPage as $front_value) - { - if(is_array($front_value['page'])) - { // Its a URL with multiple options - foreach($front_value['page'] as $multipage) - { - if($path == $multipage['page']) - { - // return $front_value['title'].":".$path; - return $front_value['title'].":".$multipage['title']; - } - } - } - else - { - if($path == $front_value['page']) - { - return $front_value['title']; - } - } - } - if(strlen($path)) - return FRTLAN_51.":".$path; // 'Other' - else - return LAN_NONE; // 'None' - } - - - - /** - * Show the selection options for a possible target of a rule - * - * @param string $ob_name - name of the radio button which selects this element - * @param string $front_key - * @param array|string $front_value - array of choices, or a single value - * @param boolean $is_other - passed by reference - set if some other option is selected - * @param string $current_setting - current value - * - * @return string - text for display - */ - function show_front_val($ob_name, $front_key, $front_value, &$is_other, $current_setting) - { - $type_selected = FALSE; - $text = ''; - - // First, work out if the selection os one of these options - if (is_array($front_value['page'])) - { // Its a URL with multiple options - foreach($front_value['page'] as $multipage) - { - if($current_setting == $multipage['page']) - { - $type_selected = TRUE; - $is_other = FALSE; - } - } - } - else - { - if($current_setting == $front_value['page']) - { - $type_selected = TRUE; - $is_other = FALSE; - } - } - - // Now generate the display text - two table cells worth - if (is_array($front_value['page'])) - { // Multiple options for same page name - $text .= " - - ".$this->frm->radio($ob_name, $front_key, $type_selected, array('label'=>$front_value['title']))." - - - "; - $text .= $this->frm->select_open($ob_name.'_multipage['.$front_key.']', 'size=xxlarge'); - foreach($front_value['page'] as $multipage_key => $multipage_value) - { - $text .= "\n".$this->frm->option($multipage_value['title'], $multipage_key, ($current_setting == $multipage_value['page']))."\n"; - } - $text .= $this->frm->select_close(); - - - $text .= ""; - } - else - { // Single option for URL - $text .= " - - ".$this->frm->radio($ob_name, $front_key, $type_selected, array('label'=>$front_value['title']))." - - - ".vartrue($front_value['diz']," ").""; - } - return $text; - } - - - - /** - * Provide the text for an 'other' option - a text box for URL entry - * - * @param string $ob_name - name of the radio button which selects this element - * @param string $front_key - * @param string $curval - current 'selected' value - * @param string $cur_page - probably the secondary (e.g. custom page) value for any option that has one - * - * @return string - text for display - */ - function add_other($ob_name, $cur_val, $cur_page) - { - $label = ($cur_val) ? LAN_CUSTOM_URL_DISABLED : LAN_CUSTOM_URL; - - return " - ".$this->frm->radio($ob_name, 'other', $cur_val, array('label'=> $label))." - ".$this->frm->text($ob_name.'_other', ($cur_val ? $cur_page : ''), 150, "size=xxlarge&id={$ob_name}-other-txt")." - "; - } -} - -require_once(e_ADMIN.'footer.php'); - -/** - * Log event to admin log - * - * @param string $msg_num - exactly two numeric characters corresponding to a log message - * @param string $woffle - information for the body of the log entre - * - * @return none - */ -function frontpage_adminlog($msg_num = '00', $woffle = '') -{ - e107::getAdminLog()->log_event('FRONTPG_'.$msg_num, $woffle, E_LOG_INFORMATIVE, ''); -} - - -function frontpage_adminmenu() -{ - - $action = vartrue($_GET['mode'],'main'); - - $var['main']['text'] = LAN_MANAGE; - $var['main']['link'] = e_SELF; - $var['create']['text'] = LAN_CREATE; - $var['create']['link'] = e_SELF."?mode=create"; - - $icon = e107::getParser()->toIcon('e-frontpage-24'); - $caption = $icon."".FRTLAN_PAGE_TITLE.""; - - - show_admin_menu($caption, $action, $var); -} - - + 'news.php', 'title' => ADLAN_0); // TODO Move to e107_plugins/news + +$front_page['wmessage'] = array('page' => 'index.php', 'title' => ADLAN_28, 'diz'=>'index.php'); + +if($sql->db_Select('page', 'page_id, page_title', "menu_name=''")) // TODO Move to e107_plugins/page +{ + $front_page['custom']['title'] = FRTLAN_30; + while($row = $sql->db_Fetch()) + { + $front_page['custom']['page'][] = array('page' => 'page.php?'.$row['page_id'], 'title' => $row['page_title']); + } +} + +// Now let any plugins add to the options - must append to the $front_page array as above + + + //v2.x spec. ---------- + $new = e107::getAddonConfig('e_frontpage'); + foreach($new as $k=>$v) + { + $front_page[$k] = $v; + } + + // v1.x spec.--------------- + if(!empty($frontPref['e_frontpage_list'])) + { + foreach($frontPref['e_frontpage_list'] as $val) + { + if(is_readable(e_PLUGIN.$val.'/e_frontpage.php')) + { + require_once (e_PLUGIN.$val.'/e_frontpage.php'); + } + } + } + + + +// Make sure links relative to SITEURL +foreach($front_page as &$front_value) +{ + if(is_array($front_value['page'])) + { // Its a URL with multiple options + foreach($front_value['page'] as &$multipage) + { + $multipage = str_replace(e_HTTP, '', $multipage); + //if (substr($multipage, 0, 1) != '/') $multipage = '/'.$multipage; + } + } + else + { + $front_value = str_replace(e_HTTP, '', $front_value); + //if (substr($front_value, 0, 1) != '/') $front_value = '/'.$front_value; + } +} + +// print_a($front_page); + + +// Now sort out list of rules for display (based on $pref data to start with) +$gotpub = FALSE; +if(is_array($frontPref['frontpage'])) +{ + $i = 1; + foreach($frontPref['frontpage'] as $class => $val) + { + if($class == 'all') + { + $class = e_UC_PUBLIC; + $gotpub = TRUE; + } + if($val) + { // Only add non-null pages + $fp_settings[$i] = array('order' => $i, 'class' => $class, 'page' => $val, 'force' => varset($frontPref['frontpage_force'][$class], '')); + $i ++; + } + } +} +else +{ // Legacy stuff to convert + $fp_settings = array(); + $fp_settings[] = array('order' => 0, 'class' => e_UC_PUBLIC, 'page' => varset($frontPref['frontpage'], 'news.php'), 'force' => ''); +} + +if(!$gotpub) +{ // Need a 'default' setting - usually 'all' + $fp_settings[] = array('order' => $i, 'class' => e_UC_PUBLIC, 'page' => (isset($frontPref['frontpage']['all']) ? $frontPref['frontpage']['all'] : 'news.php'), 'force' => ''); +} + +$fp_update_prefs = FALSE; + + +/* +Following code replaced - values not passed on image clicks with Firefox +if(isset($_POST['fp_inc'])) +{ + $mv = intval($_POST['fp_inc']); + echo "Increment: {$mv}
"; + if(($mv > 1) && ($mv <= count($fp_settings))) + { + $temp = $fp_settings[$mv - 1]; + $fp_settings[$mv - 1] = $fp_settings[$mv]; + $fp_settings[$mv] = $temp; + $fp_update_prefs = TRUE; + frontpage_adminlog('01', 'Inc '.$mv); + } +} +elseif(isset($_POST['fp_dec'])) +{ + $mv = intval($_POST['fp_dec']); + echo "Decrement: {$mv}
"; + if(($mv > 0) && ($mv < count($fp_settings))) + { + $temp = $fp_settings[$mv + 1]; + $fp_settings[$mv + 1] = $fp_settings[$mv]; + $fp_settings[$mv] = $temp; + $fp_update_prefs = TRUE; + frontpage_adminlog('01', 'Dec '.$mv); + } +} +*/ + +if (isset($_POST)) +{ + + // avoid endless loop. + if($_POST['frontpage'] == 'other' && (trim($_POST['frontpage_other']) == 'index.php' || trim($_POST['frontpage_other']) == '{e_BASE}index.php')) + { + $_POST['frontpage'] = 'wmessage'; + $_POST['frontpage_other'] = ''; + } + + + foreach ($_POST as $k => $v) + { + $incDec = substr($k, 0, 6); + $idNum = substr($k, 6); + if ($incDec == 'fp_inc') + { + $mv = intval($idNum); + if(($mv > 1) && ($mv <= count($fp_settings))) + { + $temp = $fp_settings[$mv - 1]; + $fp_settings[$mv - 1] = $fp_settings[$mv]; + $fp_settings[$mv] = $temp; + $fp_update_prefs = TRUE; + frontpage_adminlog('01', 'Inc '.$mv); + } + break; + } + elseif ($incDec == 'fp_dec') + { + $mv = intval($idNum); + if(($mv > 0) && ($mv < count($fp_settings))) + { + $temp = $fp_settings[$mv + 1]; + $fp_settings[$mv + 1] = $fp_settings[$mv]; + $fp_settings[$mv] = $temp; + $fp_update_prefs = TRUE; + frontpage_adminlog('01', 'Dec '.$mv); + } + break; + } + } +} + + + +// Edit an existing rule +if(isset($_POST['fp_edit_rule'])) +{ + $_POST['type'] = (isset($_POST['edit']['all'])) ? 'all_users' : 'user_class'; + $_POST['class'] = key($_POST['edit']); +} + +// Cancel Edit + + +if(isset($_POST['fp_save_new'])) +{ // Add or edit an existing rule here. + // fp_order - zero for a new rule, non-zero if editing an existing rule + // class - user class for rule + // frontpage - radio button option indicating type of page (for home page) + // frontpage_multipage[] - the other information for custom pages and similar - array index matches value of 'frontpage' when selected + // frontpage_other - URL for 'other' home page + // fp_force_page - radio button option indicating type of page (for post-login page) + // fp_force_page_multipage[] - the other information for custom pages and similar - array index matches value of 'frontpage' when selected + // fp_force_page_other - URL for forced post-login 'other' page + + + if($_POST['frontpage'] == 'other') + { + $_POST['frontpage_other'] = trim($tp->toForm($_POST['frontpage_other'])); + $frontpage_value = $_POST['frontpage_other'] ? $_POST['frontpage_other'] : 'news.php'; + } + else + { + if(is_array($front_page[$_POST['frontpage']]['page'])) + { + $frontpage_value = $front_page[$_POST['frontpage']]['page'][$_POST['frontpage_multipage'][$_POST['frontpage']]]['page']; + } + else + { + $frontpage_value = $front_page[$_POST['frontpage']]['page']; + } + } + + if($_POST['fp_force_page'] == 'other') + { + $_POST['fp_force_page_other'] = trim($tp->toForm($_POST['fp_force_page_other'])); + $forcepage_value = $_POST['fp_force_page_other']; // A null value is allowable here + } + else + { + if(is_array($front_page[$_POST['fp_force_page']]['page'])) + { + $forcepage_value = $front_page[$_POST['fp_force_page']]['page'][$_POST['fp_force_page_multipage'][$_POST['fp_force_page']]]['page']; + } + else + { + $forcepage_value = $front_page[$_POST['fp_force_page']]['page']; + } + } + + $temp = array('order' => intval($_POST['fp_order']), 'class' => $_POST['class'], 'page' => $frontpage_value, 'force' => trim($forcepage_value)); + + if($temp['order'] == 0) // New index to add + { + $ind = 0; + for($i = 1; $i <= count($fp_settings); $i ++) + { + if($fp_settings[$i]['class'] == $temp['class']) + $ind = $i; + } + + if($ind) + { + $mes->addDebug(print_a($fp_settings,true)); + $mes->addError(FRTLAN_56." ".$ind); + unset($fp_settings[$ind]); // Knock out duplicate definition for class + } + + array_unshift($fp_settings, $temp); // Deliberately add twice + array_unshift($fp_settings, $temp); // ....because re-indexed from zero + unset($fp_settings[0]); // Then knock out index zero + $fp_update_prefs = TRUE; + frontpage_adminlog('02', "class => {$_POST['class']},[!br!]page => {$frontpage_value},[!br!]force => {$forcepage_value}"); + } + elseif(array_key_exists($temp['order'], $fp_settings)) + { + $fp_settings[$temp['order']] = $temp; + $fp_update_prefs = TRUE; + frontpage_adminlog('03', "posn => {$temp},[!br!]class => {$_POST['class']},[!br!]page => {$frontpage_value},[!br!]force => {$forcepage_value}"); + } + else + { // Someone playing games + $mes->addError(FRTLAN_57); + } +} + +if(isset($_POST['fp_delete_rule'])) +{ + if(isset($fp_settings[key($_POST['fp_delete_rule'])])) + { + $rule_no = key($_POST['fp_delete_rule']); + $array_size = count($fp_settings); + frontpage_adminlog('04', "Rule {$rule_no},[!br!]class => {$fp_settings[$rule_no]['class']},[!br!]page => {$fp_settings[$rule_no]['page']},[!br!]force => {$fp_settings[$rule_no]['force']}"); + unset($fp_settings[$rule_no]); + while($rule_no < $array_size) + { // Move up and renumber any entries after the deleted rule + $fp_settings[$rule_no] = $fp_settings[$rule_no + 1]; + $rule_no ++; + unset($fp_settings[$rule_no]); + } + $fp_update_prefs = TRUE; + } +} + +if($fp_update_prefs) +{ // Save the two arrays + $fp_list = array(); + $fp_force = array(); + for($i = 1; $i <= count($fp_settings); $i ++) + { + $fp_list[$fp_settings[$i]['class']] = $fp_settings[$i]['page']; + $fp_force[$fp_settings[$i]['class']] = $fp_settings[$i]['force']; + } + + $corePrefs = e107::getConfig('core'); // Core Prefs Object. + $corePrefs->set('frontpage', $fp_list); + $corePrefs->set('frontpage_force', $fp_force); + $result = $corePrefs->save(FALSE, TRUE); + $mes->addDebug("

Home

".print_a($fp_list, true)); + $mes->addDebug("

Post-Login

".print_a($fp_force, true)); +} + + + + +// All updates complete now - latest data is in the $fp_settings, $fp_list and $fp_force arrays +$fp = new frontpage($front_page); + + + + + +class frontpage +{ + protected $frm; + protected $frontPage = array(); // List of options for front page + + public function __construct($fp) + { + $this->frm = e107::getForm(); + $this->frontPage = $fp; + + $ns = e107::getRender(); + $mes = e107::getMessage(); + + global $fp_settings; + + + if(vartrue($_GET['mode']) == 'create') + { + $text = $this->edit_rule(array('order' => 0, 'class' => e_UC_PUBLIC, 'page' => 'news.php', 'force' => FALSE)); // Display edit form as well + // $text .= $this->select_class($fp_settings, FALSE); + $ns->tablerender(FRTLAN_PAGE_TITLE.SEP.FRTLAN_42, $text); + } + elseif(vartrue($_GET['id'])) + { + $key = intval($_GET['id']); + $text = $this->edit_rule($fp_settings[$key]); // Display edit form as well + // $text .= $this->select_class($fp_settings, FALSE); + $ns->tablerender(FRTLAN_PAGE_TITLE.SEP.FRTLAN_46, $text); + } + else + { // Just show existing rules + $ns->tablerender(FRTLAN_PAGE_TITLE.SEP.FRTLAN_13, $mes->render().$this->select_class($fp_settings, TRUE)); + } + + } + + + + /** + * Show a list of existing rules, with edit/delete/move buttons, and optional button to add a new rule + * + * @param boolean $show_button - show the 'Add new rule' button if true + * + * @return string text for display + */ + function select_class(&$fp_settings, $show_button = TRUE) + { + $frm = e107::getForm(); + // List of current settings + $show_legend = $show_button ? " class='e-hideme'" : ''; + $text = " +
+ +
+ ".FRTLAN_13." + + + + + + + + + + + + + + + + + + + "; + + foreach($fp_settings as $order => $current_value) + { + $title = e107::getUserClass()->getName($current_value['class']); + $text .= " + + + + + + + "; + + + } + $text .= " + +
".LAN_ORDER."".LAN_USERCLASS."".FRTLAN_49."".FRTLAN_35."".LAN_OPTIONS."
".$order."".$title."".$this->lookup_path($current_value['page'])."".$this->lookup_path($current_value['force'])." +
"; + + // ".$frm->admin_button('fp_inc',$order,'up',ADMIN_UP_ICON)." + // ".$frm->admin_button('fp_dec',$order,'down',ADMIN_DOWN_ICON)." + + $text .= " + ".ADMIN_EDIT_ICON." + ".$frm->admin_button('fp_delete_rule['.$order.']',$order,'',ADMIN_DELETE_ICON)." +
+
"; + + if($show_button) + { + $text .= " + "; + } + + $text .= " +
+
"; + + return $text; + } + + + + /** + * Display form to add/edit rules + * + * @param array $rule_info - initial data (must be preset if new rule) + * + * @return string - text for display + */ + function edit_rule($rule_info) + { + $is_other_home = TRUE; + $is_other_force = TRUE; + //$force_checked = $rule_info['force'] ? " checked='checked'" : ''; + $text_tmp_1 = ''; + $text_tmp_2 = ''; + foreach($this->frontPage as $front_key => $front_value) + { + //$type_selected = FALSE; + + $text_tmp_1 .= " + + ".$this->show_front_val('frontpage', $front_key, $front_value, $is_other_home, $rule_info['page'])." + + "; + + $text_tmp_2 .= " + + ".$this->show_front_val('fp_force_page', $front_key, $front_value, $is_other_force, $rule_info['force'])." + + "; + + } + +// ".($rule_info['order'] ? FRTLAN_46 : FRTLAN_42)." + + $text = " +
+ + "; + + $text .= ' + '; + + $text .= " +
+
+ + + + + + + + + + + + +
Selection + + + + + + ".$text_tmp_1." + ".$this->add_other('frontpage', $is_other_home, $rule_info['page'])." +
+
+
+ +
+ + + + + + + + + + + +
+ + + + + + ".$text_tmp_2." + ".$this->add_other('fp_force_page', $is_other_force, $rule_info['force'])." +
+
+
+
+ + + + + + + + + + + + + +
".FRTLAN_43."".e107::getUserClass()->uc_dropdown('class', $rule_info['class'], 'public,guest,member,admin,main,classes')."
".LAN_ORDER."".$this->frm->number('fp_order', $rule_info['order'], 3, 'min=0')."
+ +
+ + ".$this->frm->admin_button('fp_save_new', LAN_UPDATE, 'update')." + ".$this->frm->admin_button('fp_cancel', LAN_CANCEL, 'cancel')." +
+ +
+ "; + return $text; + } + + + + /** + * Given a path string related to a choice, returns the 'type' (title) for it + * + * @param string $path + * + * @return string - title of option + */ + function lookup_path($path) + { + foreach($this->frontPage as $front_value) + { + if(is_array($front_value['page'])) + { // Its a URL with multiple options + foreach($front_value['page'] as $multipage) + { + if($path == $multipage['page']) + { + // return $front_value['title'].":".$path; + return $front_value['title'].":".$multipage['title']; + } + } + } + else + { + if($path == $front_value['page']) + { + return $front_value['title']; + } + } + } + if(strlen($path)) + return FRTLAN_51.":".$path; // 'Other' + else + return LAN_NONE; // 'None' + } + + + + /** + * Show the selection options for a possible target of a rule + * + * @param string $ob_name - name of the radio button which selects this element + * @param string $front_key + * @param array|string $front_value - array of choices, or a single value + * @param boolean $is_other - passed by reference - set if some other option is selected + * @param string $current_setting - current value + * + * @return string - text for display + */ + function show_front_val($ob_name, $front_key, $front_value, &$is_other, $current_setting) + { + $type_selected = FALSE; + $text = ''; + + // First, work out if the selection os one of these options + if (is_array($front_value['page'])) + { // Its a URL with multiple options + foreach($front_value['page'] as $multipage) + { + if($current_setting == $multipage['page']) + { + $type_selected = TRUE; + $is_other = FALSE; + } + } + } + else + { + if($current_setting == $front_value['page']) + { + $type_selected = TRUE; + $is_other = FALSE; + } + } + + // Now generate the display text - two table cells worth + if (is_array($front_value['page'])) + { // Multiple options for same page name + $text .= " + + ".$this->frm->radio($ob_name, $front_key, $type_selected, array('label'=>$front_value['title']))." + + + "; + $text .= $this->frm->select_open($ob_name.'_multipage['.$front_key.']', 'size=xxlarge'); + foreach($front_value['page'] as $multipage_key => $multipage_value) + { + $text .= "\n".$this->frm->option($multipage_value['title'], $multipage_key, ($current_setting == $multipage_value['page']))."\n"; + } + $text .= $this->frm->select_close(); + + + $text .= ""; + } + else + { // Single option for URL + $text .= " + + ".$this->frm->radio($ob_name, $front_key, $type_selected, array('label'=>$front_value['title']))." + + + ".vartrue($front_value['diz']," ").""; + } + return $text; + } + + + + /** + * Provide the text for an 'other' option - a text box for URL entry + * + * @param string $ob_name - name of the radio button which selects this element + * @param string $front_key + * @param string $curval - current 'selected' value + * @param string $cur_page - probably the secondary (e.g. custom page) value for any option that has one + * + * @return string - text for display + */ + function add_other($ob_name, $cur_val, $cur_page) + { + $label = ($cur_val) ? LAN_CUSTOM_URL_DISABLED : LAN_CUSTOM_URL; + + return " + ".$this->frm->radio($ob_name, 'other', $cur_val, array('label'=> $label))." + ".$this->frm->text($ob_name.'_other', ($cur_val ? $cur_page : ''), 150, "size=xxlarge&id={$ob_name}-other-txt")." + "; + } +} + +require_once(e_ADMIN.'footer.php'); + +/** + * Log event to admin log + * + * @param string $msg_num - exactly two numeric characters corresponding to a log message + * @param string $woffle - information for the body of the log entre + * + * @return none + */ +function frontpage_adminlog($msg_num = '00', $woffle = '') +{ + e107::getAdminLog()->log_event('FRONTPG_'.$msg_num, $woffle, E_LOG_INFORMATIVE, ''); +} + + +function frontpage_adminmenu() +{ + + $action = vartrue($_GET['mode'],'main'); + + $var['main']['text'] = LAN_MANAGE; + $var['main']['link'] = e_SELF; + $var['create']['text'] = LAN_CREATE; + $var['create']['link'] = e_SELF."?mode=create"; + + $icon = e107::getParser()->toIcon('e-frontpage-24'); + $caption = $icon."".FRTLAN_PAGE_TITLE.""; + + + show_admin_menu($caption, $action, $var); +} + + ?> \ No newline at end of file diff --git a/e107_admin/update_routines.php b/e107_admin/update_routines.php index 59b4a3e82..87a394a5a 100644 --- a/e107_admin/update_routines.php +++ b/e107_admin/update_routines.php @@ -1,2129 +1,2129 @@ -retrieve_sys('nq_admin_updatecheck',3600, TRUE)) - { // See when we last checked for an admin update - list($last_time, $dont_check_update, $last_ver) = explode(',',$tempData); - if ($last_ver != $e107info['e107_version']) - { - $dont_check_update = FALSE; // Do proper check on version change - } - } -} -*/ - -$dont_check_update = false; - -if (!$dont_check_update) -{ - /* - if ($sql->db_Select('plugin', 'plugin_id, plugin_version, plugin_path', 'plugin_installflag=1')) - { - while ($row = $sql->db_Fetch()) - { // Mark plugins for update which have a specific update file, or a plugin.php file to check - if(is_readable(e_PLUGIN.$row['plugin_path'].'/'.$row['plugin_path'].'_update_check.php') || is_readable(e_PLUGIN.$row['plugin_path'].'/plugin.php') || is_readable(e_PLUGIN.$row['plugin_path'].'/'.$row['plugin_path'].'_setup.php')) - { - $dbupdateplugs[$row['plugin_path']] = $row['plugin_version']; - //TODO - Add support for {plugins}_setup.php upgrade check and routine. - } - } - } - */ - - if($dbupdateplugs = e107::getConfig('core')->get('plug_installed')) - { - // Read in each update file - this will add an entry to the $dbupdatep array if a potential update exists - foreach ($dbupdateplugs as $path => $ver) - { - if(!is_file(e_PLUGIN.$path."/plugin.xml")) - { - $fname = e_PLUGIN.$path.'/'.$path.'_update_check.php'; // DEPRECATED - left for BC only. - if (is_readable($fname)) include_once($fname); - } - - $fname = e_PLUGIN.$path.'/'.$path.'_setup.php'; - if (is_readable($fname)) - { - $dbupdatep[$path] = $path ; // ' 0.7.x forums '.LAN_UPDATE_9.' 0.8 forums'; - include_once($fname); - } - } - } - - - // List of potential updates - if (defined('TEST_UPDATE')) - { - $dbupdate['test_code'] = 'Test update routine'; - } - - // set 'master' to true to prevent other upgrades from running before it is complete. - - $LAN_UPDATE_4 = deftrue('LAN_UPDATE_4',"Update from [x] to [y]"); // in case language-pack hasn't been upgraded. - $LAN_UPDATE_5 = deftrue('LAN_UPDATE_5', "Core database structure"); - -// $dbupdate['218_to_219'] = array('master'=>false, 'title'=> e107::getParser()->lanVars($LAN_UPDATE_4, array('2.1.8','2.1.9')), 'message'=> null, 'hide_when_complete'=>true); - -// $dbupdate['217_to_218'] = array('master'=>false, 'title'=> e107::getParser()->lanVars($LAN_UPDATE_4, array('2.1.7','2.1.8')), 'message'=> null, 'hide_when_complete'=>true); - - $dbupdate['20x_to_220'] = array('master'=>false, 'title'=> e107::getParser()->lanVars($LAN_UPDATE_4, array('2.x','2.2.0')), 'message'=> null, 'hide_when_complete'=>false); - - $dbupdate['706_to_800'] = array('master'=>true, 'title'=> e107::getParser()->lanVars($LAN_UPDATE_4, array('1.x','2.0')), 'message'=> LAN_UPDATE_29, 'hide_when_complete'=>true); - - - // always run these last. - $dbupdate['core_database'] = array('master'=>false, 'title'=> $LAN_UPDATE_5); - $dbupdate['core_prefs'] = array('master'=>true, 'title'=> LAN_UPDATE_13); // Prefs check - - - -// $dbupdate['70x_to_706'] = LAN_UPDATE_8.' .70x '.LAN_UPDATE_9.' .706'; -} // End if (!$dont_check_update) - - - -// New in v2.x ------------------------------------------------ - -class e107Update -{ - var $core = array(); - var $updates = 0; - var $disabled = 0; - - - function __construct($core=null) - { - $mes = e107::getMessage(); - - $this->core = $core; - - if(varset($_POST['update_core']) && is_array($_POST['update_core'])) - { - $func = key($_POST['update_core']); - $this->updateCore($func); - } - - if(varset($_POST['update']) && is_array($_POST['update'])) // Do plugin updates - { - $func = key($_POST['update']); - $this->updatePlugin($func); - } - - // $dbv = e107::getSingleton('db_verify', e_HANDLER."db_verify_class.php"); - - // $dbv->clearCache(); - - - $this->renderForm(); - } - - - - - function updateCore($func='') - { - $mes = e107::getMessage(); - $tp = e107::getParser(); - $sql = e107::getDb(); - - - // foreach($this->core as $func => $data) - // { - if(function_exists('update_'.$func)) // Legacy Method. - { - $installed = call_user_func("update_".$func); - //?! (LAN_UPDATE == $_POST[$func]) - if(vartrue($_POST['update_core'][$func]) && !$installed) - { - if(function_exists("update_".$func)) - { - // $message = LAN_UPDATE_7." ".$func; - $message = $tp->lanVars(LAN_UPDATE_7, $this->core[$func]['title']); - $error = call_user_func("update_".$func, "do"); - - if($error != '') - { - $mes->add($message, E_MESSAGE_ERROR); - $mes->add($error, E_MESSAGE_ERROR); - } - else - { - $mes->add($message, E_MESSAGE_SUCCESS); - } - } - } - } - else - { - $mes->addDebug("could not run 'update_".$func); - } - - //} - - } - - - - function updatePlugin($path) - { - e107::getPlugin()->install_plugin_xml($path, 'upgrade'); - // e107::getPlugin()->save_addon_prefs(); // Rebuild addon prefs. - e107::getMessage()->reset(E_MESSAGE_INFO); - e107::getMessage()->addSuccess(LAN_UPDATED." : ".$path); - - } - - - - function plugins() - { - if(!$list = e107::getPlugin()->updateRequired()) - { - return false; - } - - $frm = e107::getForm(); - - $tp = e107::getParser(); - - $text = ""; - - uksort($list, "strnatcasecmp"); - - foreach($list as $path=>$val) - { - $name = !empty($val['@attributes']['lan']) ? $tp->toHTML($val['@attributes']['lan'],false,'TITLE') : $val['@attributes']['name']; - - $text .= " - ".$name." - ".$frm->admin_button('update['.$path.']', LAN_UPDATE, 'warning', '', 'disabled='.$this->disabled)." - "; - } - - return $text; - } - - - - - function core() - { - $frm = e107::getForm(); - $mes = e107::getMessage(); - $sql = e107::getDb(); - - $text = ""; - - - - foreach($this->core as $func => $data) - { - $text2 = ''; - - if(function_exists("update_".$func)) - { - - if(call_user_func("update_".$func)) - { - if(empty($data['hide_when_complete'])) - { - $text2 .= "".$data['title'].""; - $text2 .= "".ADMIN_TRUE_ICON.""; - } - } - else - { - $text2 .= "".$data['title'].""; - - if(vartrue($data['message'])) - { - $mes->addInfo($data['message']); - } - - $this->updates ++; - - $text2 .= "".$frm->admin_button('update_core['.$func.']', LAN_UPDATE, 'warning', '', "id=e-{$func}&disabled=".$this->disabled).""; - - if($data['master'] == true) - { - $this->disabled = 1; - } - } - - if(!empty($text2)) - { - $text .= "".$text2."\n"; - } - - } - } - - return $text; - } - - - - function renderForm() - { - $ns = e107::getRender(); - $mes = e107::getMessage(); - - $caption = LAN_UPDATE; - $text = " -
-
- {$caption} - - - - - - - - - - - - - "; - - $text .= $this->core(); - $text .= $this->plugins(); - - $text .= " - -
".LAN_UPDATE_55."".LAN_UPDATE_2."
-
-
- "; - - - $ns->tablerender(LAN_UPDATES,$mes->render() . $text); - - } - - -} - -/** - * Master routine to call to check for updates - */ -function update_check() -{ - - $ns = e107::getRender(); - $e107cache = e107::getCache(); - $sql = e107::getDb(); - $mes = e107::getMessage(); - - global $dont_check_update, $e107info; - global $dbupdate, $dbupdatep, $e107cache; - - $update_needed = FALSE; - - - - if ($dont_check_update === FALSE) - { - $dbUpdatesPref = array(); - - $skip = e107::getPref('db_updates'); - - foreach($dbupdate as $func => $rmks) // See which core functions need update - { - - if(!empty($skip[$func]) && (!deftrue('e_DEBUG') || E107_DBG_TIMEDETAILS)) // skip version checking when debug is off and check already done. - { - continue; - } - - if(function_exists('update_' . $func)) - { - - $sql->db_Mark_Time('Check Core Update_' . $func . ' '); - if(!call_user_func('update_' . $func, false)) - { - $dbUpdatesPref[$func] = 0; - $update_needed = true; - break; - } - elseif(strpos($func, 'core_') !==0) // skip the pref and table check. - { - $dbUpdatesPref[$func] = 1; - - } - } - - } - - e107::getConfig()->set('db_updates', $dbUpdatesPref)->save(false,true,false); - - - // Now check plugins - XXX DEPRECATED - foreach($dbupdatep as $func => $rmks) - { - if(function_exists('update_' . $func)) - { - // $sql->db_Mark_Time('Check Core Update_'.$func.' '); - if(!call_user_func('update_' . $func, false)) - { - $update_needed = true; - break; - } - } - } - - // New in v2.x - if(e107::getPlugin()->updateRequired('boolean')) - { - $update_needed = TRUE; - } - - - // $e107cache->set_sys('nq_admin_updatecheck', time().','.($update_needed ? '2,' : '1,').$e107info['e107_version'], TRUE); - } - else - { - $update_needed = ($dont_check_update == '2'); - } - - return $update_needed; -} - - -//XXX to be reworked eventually - for checking remote 'new versions' of plugins and installed theme. -// require_once(e_HANDLER.'e_upgrade_class.php'); -// $upg = new e_upgrade; - -// $upg->checkSiteTheme(); -// $upg->checkAllPlugins(); - - - -//-------------------------------------------- -// Check current prefs against latest list -//-------------------------------------------- -function update_core_prefs($type='') -{ - global $e107info; // $pref, $pref must be kept as global - - $pref = e107::getConfig('core', true, true)->getPref(); - $admin_log = e107::getAdminLog(); - $do_save = FALSE; - $should = get_default_prefs(); - - $just_check = $type == 'do' ? FALSE : TRUE; // TRUE if we're just seeing if an update is needed - - foreach ($should as $k => $v) - { - if ($k && !array_key_exists($k,$pref)) - { - if ($just_check) return update_needed('Missing pref: '.$k); - // $pref[$k] = $v; - e107::getConfig()->set($k,$v); - $admin_log->logMessage($k.' => '.$v, E_MESSAGE_NODISPLAY, E_MESSAGE_INFO); - $do_save = TRUE; - } - } - if ($do_save) - { - //save_prefs(); - e107::getConfig('core')->save(false,true); - $admin_log->logMessage(LAN_UPDATE_14.$e107info['e107_version'], E_MESSAGE_NODISPLAY, E_MESSAGE_INFO); - $admin_log->flushMessages('UPDATE_03',E_LOG_INFORMATIVE); - //e107::getLog()->add('UPDATE_03',LAN_UPDATE_14.$e107info['e107_version'].'[!br!]'.implode(', ',$accum),E_LOG_INFORMATIVE,''); // Log result of actual update - } - return $just_check; -} - - - -if (defined('TEST_UPDATE')) -{ -//-------------------------------------------- -// Test routine - to activate, define TEST_UPDATE -//-------------------------------------------- - function update_test_code($type='') - { - global $sql,$ns, $pref; - $just_check = $type == 'do' ? FALSE : TRUE; // TRUE if we're just seeing whether an update is needed - //--------------**************--------------- - // Add your test code in here - //--------------**************--------------- - - //--------------**************--------------- - // End of test code - //--------------**************--------------- - return $just_check; - } -} // End of test routine - -// generic database structure update. -function update_core_database($type = '') -{ - $just_check = ($type == 'do') ? FALSE : TRUE; -// require_once(e_HANDLER."db_verify_class.php"); -// $dbv = new db_verify; - - /** @var db_verify $dbv */ - $dbv = e107::getSingleton('db_verify', e_HANDLER."db_verify_class.php"); - - $log = e107::getAdminLog(); - - if($plugUpgradeReq = e107::getPlugin()->updateRequired()) - { - $exclude = array_keys($plugUpgradeReq); // search xxxxx_setup.php and check for 'upgrade_required()' == true. - asort($exclude); - } - else - { - $exclude = false; - } - - $dbv->compareAll($exclude); // core & plugins, but not plugins calling for an update with xxxxx_setup.php - - - if($dbv->errors()) - { - if ($just_check) - { - $mes = e107::getMessage(); - // $mes->addDebug(print_a($dbv->errors,true)); - $log->addDebug(print_a($dbv->errors,true)); - $tables = implode(", ", array_keys($dbv->errors)); - return update_needed("Database Tables require updating: ".$tables.""); - } - - $dbv->compileResults(); - $dbv->runFix(); // Fix entire core database structure and plugins too. - - - } - - - return $just_check; -} - -/* - function update_218_to_219($type='') - { - $sql = e107::getDb(); - $just_check = ($type == 'do') ? false : true; - - // add common video and audio media categories if missing. - $count = $sql->select("core_media_cat","*","media_cat_category = '_common_video' LIMIT 1 "); - - if(!$count) - { - if ($just_check) return update_needed('Media-Manager is missing the video and audio categories and needs to be updated.'); - - $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_video', '(Common Videos)', '', 'Media in this category will be available in all areas of admin. ', 253, '', 0);"); - $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_audio', '(Common Audio)', '', 'Media in this category will be available in all areas of admin. ', 253, '', 0);"); - } - - - - return $just_check; - }*/ - - - - - /** - * @param string $type - * @return bool true = no update required, and false if update required. - */ -/* function update_217_to_218($type='') - { - $just_check = ($type == 'do') ? false : true; - - $e_user_list = e107::getPref('e_user_list'); - - e107::getPlug()->clearCache()->buildAddonPrefLists(); - if(empty($e_user_list['user'])) // check e107_plugins/user/e_user.php is registered. - { - if($just_check) - { - return update_needed("user/e_user.php need to be registered"); // NO LAN. - } - - } - - - // Make sure, that the pref "post_script" contains one of the allowed userclasses - // Close possible security hole - if (!array_key_exists(e107::getPref('post_script'), e107::getUserClass()->uc_required_class_list('nobody,admin,main,classes,no-excludes', true))) - { - if ($just_check) - { - return update_needed("Pref 'Class which can post < script > and similar tags' contains an invalid value"); // NO LAN. - } - else - { - e107::getConfig()->setPref('post_script', 255)->save(false, true); - } - } - - - return $just_check; - - - - }*/ - - - - /** - * @param string $type - * @return bool true = no update required, and false if update required. - */ - function update_20x_to_220($type='') - { - - $sql = e107::getDb(); - $log = e107::getLog(); - $just_check = ($type == 'do') ? false : true; - $pref = e107::getPref(); - - - if(!$sql->select('core_media_cat', 'media_cat_id', "media_cat_category = '_icon_svg' LIMIT 1")) - { - if($just_check) - { - return update_needed("Missing Media-category for SVG"); - } - - $query = "INSERT INTO `#core_media_cat` (media_cat_id, media_cat_owner, media_cat_category, media_cat_title, media_cat_sef, media_cat_diz, media_cat_class, media_cat_image, media_cat_order) VALUES (NULL, '_icon', '_icon_svg', 'Icons SVG', '', 'Available where icons are used in admin.', '253', '', '0');"; - - $sql->gen($query); - - } - - - - if(isset($pref['e_header_list']['social'])) - { - if($just_check) - { - return update_needed("Social Plugin Needs to be refreshed. "); - } - - e107::getPlugin()->refresh('social'); - } - - - if(empty($pref['themecss'])) // FIX - { - if($just_check) - { - return update_needed("Theme CSS pref value is blank."); - } - - e107::getConfig()->set('themecss','style.css')->save(false,true,false); - } - - - // User is marked as not installed. - if($sql->select('plugin', 'plugin_id', "plugin_path = 'user' AND plugin_installflag != 1 LIMIT 1")) - { - if($just_check) - { - return update_needed("Plugin table 'user' value needs to be reset."); - } - - $sql->delete('plugin', "plugin_path = 'user'"); - - //e107::getPlug()->clearCache(); - } - - - // Make sure, that the pref "post_script" contains one of the allowed userclasses - // Close possible security hole - if (!array_key_exists(e107::getPref('post_script'), e107::getUserClass()->uc_required_class_list('nobody,admin,main,classes,no-excludes', true))) - { - if ($just_check) - { - return update_needed("Pref 'Class which can post < script > and similar tags' contains an invalid value"); // NO LAN. - } - else - { - e107::getConfig()->setPref('post_script', 255)->save(false, true); - } - } - - - // add common video and audio media categories if missing. - $count = $sql->select("core_media_cat","*","media_cat_category = '_common_video' LIMIT 1 "); - - if(!$count) - { - if ($just_check) return update_needed('Media-Manager is missing the video and audio categories and needs to be updated.'); - - $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_video', '(Common Videos)', '', 'Media in this category will be available in all areas of admin. ', 253, '', 0);"); - $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_audio', '(Common Audio)', '', 'Media in this category will be available in all areas of admin. ', 253, '', 0);"); - } - - - - return $just_check; - - - - - - } - - -//-------------------------------------------- -// Upgrade later versions of 0.7.x to 0.8 -//-------------------------------------------- -function update_706_to_800($type='') -{ - - global $pref, $e107info; - global $sysprefs, $eArrayStorage; - - //$mes = new messageLog; // Combined logging and message displaying handler - //$mes = e107::getMessage(); - $log = e107::getAdminLog(); // Used for combined logging and message displaying - $sql = e107::getDb(); - $sql2 = e107::getDb('sql2'); - $tp = e107::getParser(); - $ns = e107::getRender(); - - e107::getCache()->clearAll('db'); - e107::getCache()->clear_sys('Config'); - - e107::getMessage()->setUnique(); - - // List of unwanted $pref values which can go - $obs_prefs = array('frontpage_type','rss_feeds', 'log_lvcount', 'zone', 'upload_allowedfiletype', 'real', 'forum_user_customtitle', - 'utf-compatmode','frontpage_method','standards_mode','image_owner','im_quality', 'signup_option_timezone', - 'modules', 'plug_sc', 'plug_bb', 'plug_status', 'plug_latest', 'subnews_hide_news', 'upload_storagetype', - 'signup_remote_emailcheck' - - ); - - // List of DB tables not required (includes a few from 0.6xx) - $obs_tables = array('flood', 'stat_info', 'stat_counter', 'stat_last', 'session', 'preset', 'tinymce'); - - - // List of DB tables newly required (defined in core_sql.php) (The existing dblog table gets renamed) - // No Longer required. - automatically checked against core_sql.php. -// $new_tables = array('audit_log', 'dblog', 'news_rewrite', 'core_media', 'core_media_cat','cron', 'mail_recipients', 'mail_content'); - - // List of core prefs that need to be converted from serialized to e107ArrayStorage. - $serialized_prefs = array("'emote'", "'menu_pref'", "'search_prefs'", "'emote_default'", "'pm_prefs'"); - - - - - // List of changed DB tables (defined in core_sql.php) - // No Longer required. - automatically checked against core_sql.php. - // (primarily those which have changed significantly; for the odd field write some explicit code - it'll run faster) - // $changed_tables = array('user', 'dblog', 'admin_log', 'userclass_classes', 'banlist', 'menus', - // 'plugin', 'news', 'news_category', 'online', 'page', 'links', 'comments'); - - - // List of changed DB tables from core plugins (defined in pluginname_sql.php file) - // key = plugin directory name. Data = comma-separated list of tables to check - // (primarily those which have changed significantly; for the odd field write some explicit code - it'll run faster) - // No Longer required. - automatically checked by db-verify - /* $pluginChangedTables = array('linkwords' => 'linkwords', - 'featurebox' => 'featurebox', - 'links_page' => 'links_page', - 'poll' => 'polls', - 'content' => 'pcontent' - ); - - */ -/* - $setCorePrefs = array( //modified prefs during upgrade. - 'adminstyle' => 'infopanel', - 'admintheme' => 'bootstrap', - 'admincss' => 'admin_style.css', - 'resize_dimensions' => array( - 'news-image' => array('w' => 250, 'h' => 250), - 'news-bbcode' => array('w' => 250, 'h' => 250), - 'page-bbcode' => array('w' => 250, 'h' => 250) - ) - ); -*/ - - - - - $do_save = TRUE; - - - // List of changed menu locations. - $changeMenuPaths = array( - array('oldpath' => 'siteinfo_menu', 'newpath' => 'siteinfo', 'menu' => 'sitebutton_menu'), - array('oldpath' => 'siteinfo_menu', 'newpath' => 'siteinfo', 'menu' => 'compliance_menu'), - array('oldpath' => 'siteinfo_menu', 'newpath' => 'siteinfo', 'menu' => 'powered_by_menu'), - array('oldpath' => 'siteinfo_menu', 'newpath' => 'siteinfo', 'menu' => 'sitebutton_menu'), - array('oldpath' => 'siteinfo_menu', 'newpath' => 'siteinfo', 'menu' => 'counter_menu'), - array('oldpath' => 'siteinfo_menu', 'newpath' => 'siteinfo', 'menu' => 'latestnews_menu'), - array('oldpath' => 'compliance_menu', 'newpath' => 'siteinfo', 'menu' => 'compliance_menu'), - array('oldpath' => 'powered_by_menu', 'newpath' => 'siteinfo', 'menu' => 'powered_by_menu'), - array('oldpath' => 'sitebutton_menu', 'newpath' => 'siteinfo', 'menu' => 'sitebutton_menu'), - array('oldpath' => 'counter_menu', 'newpath' => 'siteinfo', 'menu' => 'counter_menu'), - array('oldpath' => 'usertheme_menu', 'newpath' => 'user', 'menu' => 'usertheme_menu'), - array('oldpath' => 'userlanguage_menu', 'newpath' => 'user', 'menu' => 'userlanguage_menu'), - array('oldpath' => 'lastseen_menu', 'newpath' => 'online', 'menu' => 'lastseen_menu'), - array('oldpath' => 'other_news_menu', 'newpath' => 'news', 'menu' => 'other_news_menu'), - array('oldpath' => 'other_news_menu', 'newpath' => 'news', 'menu' => 'other_news2_menu'), - array('oldpath' => 'user_menu', 'newpath' => 'user', 'menu' => 'usertheme_menu'), - array('oldpath' => 'user_menu', 'newpath' => 'user', 'menu' => 'userlanguage_menu'), - array('oldpath' => 'poll_menu', 'newpath' => 'poll', 'menu' => 'poll_menu'), - array('oldpath' => 'banner_menu', 'newpath' => 'banner', 'menu' => 'banner_menu'), - array('oldpath' => 'online_menu', 'newpath' => 'online', 'menu' => 'online_menu'), - ); - - - // List of DB tables (key) and field (value) which need changing to accommodate IPV6 addresses - $ip_upgrade = array('download_requests' => 'download_request_ip', - 'submitnews' => 'submitnews_ip', - 'tmp' => 'tmp_ip', - 'chatbox' => 'cb_ip' - ); - - $db_parser = new db_table_admin; // Class to read table defs and process them - $do_save = FALSE; // Set TRUE to update prefs when update complete - $updateMessages = array(); // Used to log actions for the admin log - TODO: will go once all converted to new class - - $just_check = ($type == 'do') ? FALSE : TRUE; // TRUE if we're just seeing whether an update is needed - -// if (!$just_check) -// { - // foreach(vartrue($setCorePrefs) as $k=>$v) - // { - // $pref[$k] = $v; - // } -// } - - if (!$just_check) - { - $log->logMessage(LAN_UPDATE_14.$e107info['e107_version'], E_MESSAGE_NODISPLAY); - } - - - - - - - - $statusTexts = array(E_MESSAGE_SUCCESS => 'Success', E_MESSAGE_ERROR => 'Fail', E_MESSAGE_INFO => 'Info'); - - - - if($pref['admintheme'] == 'bootstrap')//TODO Force an admin theme update or not? - { - if ($just_check) return update_needed('pref: Admin theme upgrade to bootstrap3 '); - - $pref['admintheme'] = 'bootstrap3'; - $pref['admincss'] = 'admin_dark.css'; - - $do_save = true; - } - - // convert all serialized core prefs to e107 ArrayStorage; - $serialz_qry = "SUBSTRING( e107_value,1,5)!='array' AND e107_value !='' "; - $serialz_qry .= "AND e107_name IN (".implode(",",$serialized_prefs).") "; - if(e107::getDb()->select("core", "*", $serialz_qry)) - { - if($just_check) return update_needed('Convert serialized core prefs'); - while ($row = e107::getDb()->fetch()) - { - - $status = e107::getDb('sql2')->update('core',"e107_value=\"".convert_serialized($row['e107_value'])."\" WHERE e107_name='".$row['e107_name']."'") ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR; - - $log->addDebug(LAN_UPDATE_22.$row['e107_name'].": ". $status); - } - } - - - if(e107::getDb()->select("core", "*", "e107_name='pm_prefs' LIMIT 1")) - { - if ($just_check) return update_needed('Rename the pm prefs'); - e107::getDb()->update("core", "e107_name='plugin_pm' WHERE e107_name = 'pm_prefs'"); - } - - - //@TODO de-serialize the user_prefs also. - - - // Banlist - - if(!$sql->field('banlist','banlist_id')) - { - if ($just_check) return update_needed('Banlist table requires updating.'); - $sql->gen("ALTER TABLE #banlist DROP PRIMARY KEY"); - $sql->gen("ALTER TABLE `#banlist` ADD `banlist_id` INT( 11 ) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST"); - } - - - - - - - // Move the maximum online counts from menu prefs to a separate pref - 'history' - e107::getCache()->clear_sys('Config'); - $menuConfig = e107::getConfig('menu',true,true); - - if ($menuConfig->get('most_members_online') || $menuConfig->get('most_guests_online') || $menuConfig->get('most_online_datestamp')) - { - $status = E_MESSAGE_DEBUG; - if ($just_check) return update_needed('Move online counts from menupref'); - $newPrefs = e107::getConfig('history'); - foreach (array('most_members_online', 'most_guests_online', 'most_online_datestamp') as $v) - { - if (FALSE === $newPrefs->get($v, FALSE)) - { - if (FALSE !== $menuConfig->get($v, FALSE)) - { - $newPrefs->set($v,$menuConfig->get($v)); - } - else - { - $newPrefs->set($v, 0); - } - } - $menuConfig->remove($v); - } - $result = $newPrefs->save(false, true, false); - if ($result === TRUE) - { - $resultMessage = 'Historic member counts updated'; - $result = $menuConfig->save(false, true, false); // Only re-save if successul. - } - elseif ($result === FALSE) - { - $resultMessage = 'moving historic member counts'; - $status = E_MESSAGE_ERROR; - } - else - { // No change - $resultMessage = 'Historic member counts already updated'; - $status = E_MESSAGE_INFO; - } - // $result = $menuConfig->save(false, true, false); // Save updated menuprefs - without the counts - don't delete them if it fails. - //$updateMessages[] = $statusTexts[$status].': '.$resultMessage; // Admin log message - $log->logMessage($resultMessage,$status); // User message - } - - - - // ++++++++ Modify Menu Paths +++++++. - if(varset($changeMenuPaths)) - { - foreach($changeMenuPaths as $val) - { - $qry = "SELECT menu_path FROM `#menus` WHERE menu_name = '".$val['menu']."' AND (menu_path='".$val['oldpath']."' || menu_path='".$val['oldpath']."/' ) LIMIT 1"; - if($sql->gen($qry)) - { - if ($just_check) return update_needed('Menu path changed required: '.$val['menu'].' '); - $updqry = "menu_path='".$val['newpath']."/' WHERE menu_name = '".$val['menu']."' AND (menu_path='".$val['oldpath']."' || menu_path='".$val['oldpath']."/' ) "; - $status = $sql->update('menus', $updqry) ? E_MESSAGE_DEBUG : E_MESSAGE_ERROR; - $log->logMessage(LAN_UPDATE_23.''.$val['menu'].' : '.$val['oldpath'].' => '.$val['newpath'], $status); // LAN_UPDATE_25; - // catch_error($sql); - } - } - } - - // Leave this one here.. just in case.. - //delete record for online_extended_menu (now only using one online menu) - if($sql->db_Select('menus', '*', "menu_path='online_extended_menu' || menu_path='online_extended_menu/'")) - { - if ($just_check) return update_needed("The Menu table needs to have some paths corrected in its data."); - - $row=$sql->db_Fetch(); - - //if online_extended is activated, we need to activate the new 'online' menu, and delete this record - if($row['menu_location']!=0) - { - $status = $sql->update('menus', "menu_name='online_menu', menu_path='online/' WHERE menu_path='online_extended_menu' || menu_path='online_extended_menu/' ") ? E_MESSAGE_DEBUG : E_MESSAGE_ERROR; - $log->logMessage(LAN_UPDATE_23."online_menu : online/", $status); - } - else - { //else if the menu is not active - //we need to delete the online_extended menu row, and change the online_menu to online - $sql->delete('menus', " menu_path='online_extended_menu' || menu_path='online_extended_menu/' "); - $log->logMessage(LAN_UPDATE_31, E_MESSAGE_DEBUG); - } - catch_error($sql); - } - - //change menu_path for online_menu (if it still exists) - if($sql->db_Select('menus', 'menu_path', "menu_path='online_menu' || menu_path='online_menu/'")) - { - if ($just_check) return update_needed('change menu_path for online menu'); - - $status = $sql->update('menus', "menu_path='online/' WHERE menu_path='online_menu' || menu_path='online_menu/' ") ? E_MESSAGE_DEBUG : E_MESSAGE_ERROR; - $log->logMessage(LAN_UPDATE_23."online_menu : online/", $status); - catch_error($sql); - } - - if (!$just_check) - { - // Alert Admin to delete deprecated menu folders. - $chgPath = array(); - foreach($changeMenuPaths as $cgpArray) - { - if(is_dir(e_PLUGIN.$cgpArray['oldpath'])) - { - if(!in_array($cgpArray['oldpath'],$chgPath)) - { - $chgPath[] = $cgpArray['oldpath']; - } - } - } - - if(count($chgPath)) - { - $log->addWarning(LAN_UPDATE_57.' '); - array_unique($chgPath); - asort($chgPath); - foreach($chgPath as $cgp) - { - $log->addWarning(e_PLUGIN_ABS."".$cgp.""); - } - } - - } - - - -//--------------------------------------------------------- -// Comments - split user field -//--------------------------------------------------------- - if($sql->db_Field('comments','comment_author')) - { - if ($just_check) return update_needed('Comment table author field update'); - - if ((!$sql->db_Field('comments','comment_author_id')) // Check to see whether new fields already added - maybe data copy failed part way through - && (!$sql->gen("ALTER TABLE `#comments` - ADD COLUMN comment_author_id int(10) unsigned NOT NULL default '0' AFTER `comment_author`, - ADD COLUMN comment_author_name varchar(100) NOT NULL default '' AFTER `comment_author_id`"))) - { - // Flag error - // $commentMessage = LAN_UPDAXXTE_34; - $log->logMessage(LAN_UPDATE_21."comments", E_MESSAGE_ERROR); - } - else - { - if (FALSE ===$sql->update('comments',"comment_author_id=SUBSTRING_INDEX(`comment_author`,'.',1), comment_author_name=SUBSTRING(`comment_author` FROM POSITION('.' IN `comment_author`)+1)")) - { - // Flag error - $log->logMessage(LAN_UPDATE_21.'comments', E_MESSAGE_ERROR); - } - else - { // Delete superceded field - comment_author - if (!$sql->gen("ALTER TABLE `#comments` DROP COLUMN `comment_author`")) - { - // Flag error - $log->logMessage(LAN_UPDATE_24.'comments - comment_author', E_MESSAGE_ERROR); - } - } - } - - $log->logMessage(LAN_UPDATE_21.'comments', E_MESSAGE_DEBUG); - } - - - - // Add index to download history - // Deprecated by db-verify-class - // if (FALSE !== ($temp = addIndexToTable('download_requests', 'download_request_datestamp', $just_check, $updateMessages))) - // { - // if ($just_check) - // { - // return update_needed($temp); - // } - // } - - // Extra index to tmp table - // Deprecated by db-verify-class - // if (FALSE !== ($temp = addIndexToTable('tmp', 'tmp_time', $just_check, $updateMessages))) - // { - // if ($just_check) - // { - // return update_needed($temp); - // } - // } - - // Extra index to rss table (if used) - // Deprecated by db-verify-class - // if (FALSE !== ($temp = addIndexToTable('rss', 'rss_name', $just_check, $updateMessages, TRUE))) - // { - // if ($just_check) - // { - // return update_needed($temp); - // } - // } - - // Front page prefs (logic has changed) - if (!isset($pref['frontpage_force'])) // Just set basic options; no real method of converting the existing - { - if ($just_check) return update_needed('Change front page prefs'); - $pref['frontpage_force'] = array(e_UC_PUBLIC => ''); - - $fpdef = vartrue($pref['frontpage']['all']) == 'index.php' ? 'index.php' : 'news.php'; - - $pref['frontpage'] = array(e_UC_PUBLIC => $fpdef); - // $_pdateMessages[] = LAN_UPDATE_38; //FIXME - $log->logMessage(LAN_UPDATE_20."frontpage",E_MESSAGE_DEBUG); - - e107::getConfig()->add('frontpage_force', $pref['frontpage_force']); - e107::getConfig()->add('frontpage', $pref['frontpage']); - unset($pref['frontpage_force'], $pref['frontpage']); - $do_save = TRUE; - } - - // Check need for user timezone before we delete the field -// if (vartrue($pref['signup_option_timezone'])) - { - if ($sql->field('user', 'user_timezone')===true && $sql->field('user_extended','user_timezone')===false) - { - if ($just_check) return update_needed('Move user timezone info'); - if (!copy_user_timezone()) - { // Error doing the transfer - //$updateMessages[] = LAN_UPDATE_42; - $log->logMessage(LAN_UPDATE_42, E_MESSAGE_ERROR); - return FALSE; - } - //$updateMessages[] = LAN_UPDATE_41; - $log->logMessage(LAN_UPDATE_41, E_MESSAGE_DEBUG); - } - } - - - // Tables defined in core_sql.php to be RENAMED. - - - // Next bit will be needed only by the brave souls who used an early CVS - probably delete before release - if ($sql->isTable('rl_history') && !$sql->isTable('dblog')) - { - if ($just_check) return update_needed('Rename rl_history to dblog'); - $sql->gen('ALTER TABLE `'.MPREFIX.'rl_history` RENAME `'.MPREFIX.'dblog`'); - //$updateMessages[] = LAN_UPDATE_44; - $log->logMessage(LAN_UPDATE_44, E_MESSAGE_DEBUG); - catch_error($sql); - } - - - - //--------------------------------- - if ($sql->isTable('dblog') && !$sql->isTable('admin_log')) - { - if ($just_check) return update_needed('Rename dblog to admin_log'); - $sql->gen('ALTER TABLE `'.MPREFIX.'dblog` RENAME `'.MPREFIX.'admin_log`'); - catch_error($sql); - //$updateMessages[] = LAN_UPDATE_43; - $log->logMessage(LAN_UPDATE_43, E_MESSAGE_DEBUG); - } - - - if($sql->isTable('forum_t') && $sql->isEmpty('forum') && $sql->isEmpty('forum_t')) - { - if ($just_check) return update_needed('Empty forum tables need to be removed.'); - $obs_tables[] = 'forum_t'; - $obs_tables[] = 'forum'; - - } - - - // Obsolete tables (list at top) - $sql->mySQLtableList = false; // clear the cached table list. - foreach ($obs_tables as $ot) - { - if ($sql->isTable($ot)) - { - if ($just_check) return update_needed("Delete table: ".$ot); - - $status = $sql->gen('DROP TABLE `'.MPREFIX.$ot.'`') ? E_MESSAGE_DEBUG : E_MESSAGE_ERROR; - $log->logMessage(LAN_UPDATE_25.$ot, $status); - } - } - - - // Tables where IP address field needs updating to accommodate IPV6 - // Set to varchar(45) - just in case something uses the IPV4 subnet (see http://en.wikipedia.org/wiki/IPV6#Notation) - foreach ($ip_upgrade as $t => $f) - { - if ($sql->isTable($t)) - { // Check for table - might add some core plugin tables in here - if ($field_info = ($sql->db_Field($t, $f, '', TRUE))) - { - if (strtolower($field_info['Type']) != 'varchar(45)') - { - if ($just_check) return update_needed('Update IP address field '.$f.' in table '.$t); - $status = $sql->gen("ALTER TABLE `".MPREFIX.$t."` MODIFY `{$f}` VARCHAR(45) NOT NULL DEFAULT '';") ? E_MESSAGE_DEBUG : E_MESSAGE_ERROR; - $log->logMessage(LAN_UPDATE_26.$t.' - '.$f, $status); - // catch_error($sql); - } - } - else - { - // Got a strange error here - } - } - } - - - - - - - - // Obsolete prefs (list at top) - // Intentionally do this last - we may check some of them during the update - $accum = array(); - foreach ($obs_prefs as $p) - { - if (isset($pref[$p])) - { - if ($just_check) return update_needed('Remove obsolete prefs'); - unset($pref[$p]); - e107::getConfig()->remove($p); - $do_save = true; - $log->addDebug('Removed obsolete pref: '.$p); - // $accum[] = $p; - } - } - - - - - - /* -------------- Upgrade Entire Table Structure - Multi-Language Supported ----------------- */ - // ONLY ever add fields, never deletes. - -// require_once(e_HANDLER."db_verify_class.php"); -// $dbv = new db_verify; - $dbv = e107::getSingleton('db_verify', e_HANDLER."db_verify_class.php"); - - if($plugUpgradeReq = e107::getPlugin()->updateRequired()) - { - $exclude = array_keys($plugUpgradeReq); // search xxxxx_setup.php and check for 'upgrade_required()' == true. - asort($exclude); - } - else - { - $exclude = false; - } - - $dbv->compareAll($exclude); // core & plugins, but not plugins calling for an update with xxxxx_setup.php - - if(count($dbv->errors)) - { - if ($just_check) - { - $mes = e107::getMessage(); - // $mes->addDebug(print_a($dbv->errors,true)); - $log->addDebug(print_a($dbv->errors,true)); - // return update_needed("Database Tables require updating."); // - } - else - { - $dbv->compileResults(); - $dbv->runFix(); // Fix entire core database structure and plugins too. - } - } - - // print_a($dbv->results); - // print_a($dbv->fixList); - - - //TODO - send notification messages to Log. - - - if($sql->field('page','page_theme') && $sql->gen("SELECT * FROM `#page` WHERE page_theme != '' AND menu_title = '' LIMIT 1")) - { - if ($just_check) - { - return update_needed("Pages/Menus Table requires updating."); - } - - if($sql->update('page',"menu_name = page_theme, menu_title = page_title, menu_text = page_text, menu_template='default', page_title = '', page_text = '' WHERE page_theme !='' AND menu_title = '' AND menu_text IS NULL ")) - { - $sql->gen("ALTER TABLE `#page` DROP page_theme "); - $mes = e107::getMessage(); - $log->addDebug("Successfully updated pages/menus table to new format. "); - } - else - { - $log->addDebug("FAILED to update pages/menus table to new format. "); - //$sql->gen("ALTER TABLE `#page` DROP page_theme "); - } - - } - - if($sql->field('plugin','plugin_releaseUrl')) - { - if ($just_check) return update_needed('plugin_releaseUrl is deprecated and needs to be removed. '); - if($sql->gen("ALTER TABLE `#plugin` DROP `plugin_releaseUrl`")) - { - $log->addDebug("Successfully removed plugin_releaseUrl. "); - } - - } - - - // --- Notify Prefs - -// $notify_prefs = $sysprefs -> get('notify_prefs'); -// $notify_prefs = $eArrayStorage -> ReadArray($notify_prefs); - e107::getCache()->clear_sys('Config'); - - $notify_prefs = e107::getConfig('notify',true,true)->getPref(); - - $nt_changed = 0; - if(vartrue($notify_prefs['event'])) - { - foreach ($notify_prefs['event'] as $e => $d) - { - if (isset($d['type'])) - { - if ($just_check) return update_needed('Notify pref: '.$e.' outdated'); - switch ($d['type']) - { - case 'main' : - $notify_prefs['event'][$e]['class'] = e_UC_MAINADMIN; - break; - case 'class' : // Should already have class defined - break; - case 'email' : - $notify_prefs['event'][$e]['class'] = 'email'; - break; - case 'off' : // Need to disable - default : - $notify_prefs['event'][$e]['class'] = e_UC_NOBODY; // Just disable if we don't know what else to do - } - $nt_changed++; - $notify_prefs['event'][$e]['legacy'] = 1; - unset($notify_prefs['event'][$e]['type']); - } - } - } - - if ($nt_changed) - { - $s_prefs = $tp -> toDB($notify_prefs); - $s_prefs = $eArrayStorage -> WriteArray($s_prefs); - // Could we use $sysprefs->set($s_prefs,'notify_prefs') instead - avoids caching problems ???? - $status = ($sql -> update("core", "e107_value='".$s_prefs."' WHERE e107_name='notify_prefs'") !== FALSE) ? E_MESSAGE_DEBUG : E_MESSAGE_ERROR; - $message = str_replace('[x]',$nt_changed,LAN_UPDATE_20); - $log->logMessage($message, $status); - } - - - - - if (isset($pref['forum_user_customtitle']) && !isset($pref['signup_option_customtitle'])) - { - if ($just_check) return update_needed('pref: forum_user_customtitle needs to be renamed'); - // $pref['signup_option_customtitle'] = $pref['forum_user_customtitle']; - e107::getConfig()->add('signup_option_customtitle', $pref['forum_user_customtitle']); - e107::getConfig()->remove('forum_user_customtitle'); - - $log->logMessage(LAN_UPDATE_20.'customtitle', E_MESSAGE_SUCCESS); - $do_save = TRUE; - } - - - // --------------- Saved emails - copy across - - if (!$just_check && $sql->select('generic', '*', "gen_type='massmail'")) - { - if ($just_check) return update_needed('Copy across saved emails'); - require_once(e_HANDLER.'mail_manager_class.php'); - $mailHandler = new e107MailManager; - $i = 0; - while ($row = $sql->fetch()) - { - $mailRecord = array( - 'mail_create_date' => $row['gen_datestamp'], - 'mail_creator' => $row['gen_user_id'], - 'mail_title' => $row['gen_ip'], - 'mail_subject' => $row['gen_ip'], - 'mail_body' => $row['gen_chardata'], - 'mail_content_status' => MAIL_STATUS_SAVED - ); - $mailHandler->mailtoDb($mailRecord, TRUE); - $mailHandler->saveEmail($mailRecord, TRUE); - $sql2->delete('generic', 'gen_id='.intval($row['gen_id'])); // Delete as we go in case operation fails part way through - $i++; - } - unset($mailHandler); - $log->logMessage(str_replace('[x]', $i, LAN_UPDATE_28)); - } - - - - - // ------------------- Populate Plugin Table With Changes ------------------ - - if (!isset($pref['shortcode_legacy_list'])) - { - if ($just_check) return update_needed('Legacy shortcode conversion'); - // Reset, legacy and new shortcode list will be generated in plugin update routine - // $pref['shortcode_legacy_list'] = array(); - // $pref['shortcode_list'] = array(); - - e107::getConfig()->add('shortcode_legacy_list', array()); - e107::getConfig()->set('shortcode_list', array()); - e107::getConfig()->save(false,true,false); - - $ep = e107::getPlugin(); - $ep->update_plugins_table($mode); // scan for e_xxx changes and save to plugin table. - $ep->save_addon_prefs($mode); // generate global e_xxx_list prefs from plugin table. - } - - - - // This has to be done after the table is upgraded - if($sql->select('plugin', 'plugin_category', "plugin_category = ''")) - { - if ($just_check) return update_needed('Update plugin table'); - require_once(e_HANDLER.'plugin_class.php'); - $ep = new e107plugin; - $ep->update_plugins_table('update'); - // $_pdateMessages[] = LAN_UPDATE_XX24; - // catch_error($sql); - } - - - //-- Media-manger import -------------------------------------------------- - - - - // Autogenerate filetypes.xml if not found. - if(!is_readable(e_SYSTEM."filetypes.xml")) - { - $data = ' - - -'; - - file_put_contents(e_SYSTEM."filetypes.xml",$data); - } - - - - $root_media = str_replace(basename(e_MEDIA)."/","",e_MEDIA); - $user_media_dirs = array("images","avatars", "avatars/default", "avatars/upload", "files","temp","videos","icons"); - - // check for old paths and rename. - if(is_dir($root_media."images") || is_dir($root_media."temp")) - { - foreach($user_media_dirs as $md) - { - @rename($root_media.$md,e_MEDIA.$md); - } - } - - // create sub-directories if they do not exist. - if(!is_dir(e_MEDIA."images") || !is_dir(e_MEDIA."temp") || !is_dir(e_AVATAR_UPLOAD) || !is_dir(e_AVATAR_DEFAULT) ) - { - foreach($user_media_dirs as $md) - { - if(!is_dir(e_MEDIA.$md)) - { - if(mkdir(e_MEDIA.$md)===false) - { - e107::getMessage()->addWarning("Unable to create ".e_MEDIA.$md."."); - } - } - } - } - - // Move Avatars to new location - $av1 = e107::getFile()->get_files(e_FILE.'public/avatars','.jpg|.gif|.png|.GIF|.jpeg|.JPG|.PNG'); - $av2 = e107::getFile()->get_files(e_IMAGE.'avatars','.jpg|.gif|.png|.GIF|.jpeg|.JPG|.PNG'); - - $avatar_images = array_merge($av1,$av2); - - if(count($avatar_images)) - { - if ($just_check) return update_needed('Avatar paths require updating.'); - foreach($avatar_images as $av) - { - $apath = (strstr($av['path'],'public/')) ? e_AVATAR_UPLOAD : e_AVATAR_DEFAULT; - - if(rename($av['path'].$av['fname'], $apath. $av['fname'])===false) - { - e107::getMessage()->addWarning("Unable to more ".$av['path'].$av['fname']." to ".$apath. $av['fname'].". Please move manually."); - } - } - } - - // ------------------------------- - - if (!e107::isInstalled('download') && $sql->gen("SELECT * FROM #links WHERE link_url LIKE 'download.php%' AND link_class != '".e_UC_NOBODY."' LIMIT 1")) - { - if ($just_check) return update_needed('Download Plugin needs to be installed.'); - // e107::getSingleton('e107plugin')->install('download',array('nolinks'=>true)); - e107::getSingleton('e107plugin')->refresh('download'); - } - - - - if (!e107::isInstalled('banner') && $sql->isTable('banner')) - { - if ($just_check) return update_needed('Banner Table found, but plugin not installed. Needs to be refreshed.'); - e107::getSingleton('e107plugin')->refresh('banner'); - } - - // --------------------------------- - - - $med = e107::getMedia(); - - // Media Category Update - if($sql->db_Field("core_media_cat","media_cat_nick")) - { - $count = $sql->gen("SELECT * FROM `#core_media_cat` WHERE media_cat_nick = '_common' "); - if($count ==1) - { - if ($just_check) return update_needed('Media-Manager Categories needs to be updated.'); - $sql->update('core_media_cat', "media_cat_owner = media_cat_nick, media_cat_category = media_cat_nick WHERE media_cat_nick REGEXP '_common|news|page|_icon_16|_icon_32|_icon_48|_icon_64' "); - $sql->update('core_media_cat', "media_cat_owner = '_icon', media_cat_category = media_cat_nick WHERE media_cat_nick REGEXP '_icon_16|_icon_32|_icon_48|_icon_64' "); - $sql->update('core_media_cat', "media_cat_owner = 'download', media_cat_category='download_image' WHERE media_cat_nick = 'download' "); - $sql->update('core_media_cat', "media_cat_owner = 'download', media_cat_category='download_thumb' WHERE media_cat_nick = 'downloadthumb' "); - $sql->update('core_media_cat', "media_cat_owner = 'news', media_cat_category='news_thumb' WHERE media_cat_nick = 'newsthumb' "); - $log->addDebug("core-media-cat Categories and Ownership updated"); - if($sql->gen("ALTER TABLE `".MPREFIX."core_media_cat` DROP `media_cat_nick`")) - { - $log->addDebug("core-media-cat `media_cat_nick` field removed."); - } - - // $query = "INSERT INTO `".MPREFIX."core_media_cat` (`media_cat_id`, `media_cat_owner`, `media_cat_category`, `media_cat_title`, `media_cat_diz`, `media_cat_class`, `media_cat_image`, `media_cat_order`) VALUES - // (0, 'gallery', 'gallery_1', 'Gallery 1', 'Visible to the public at /gallery.php', 0, '', 0); - /// "; - // - // if(mysql_query($query)) - // { - // $log->addDebug("Added core-media-cat Gallery."); - // } - } - } - - - // Media Update - $count = $sql->gen("SELECT * FROM `#core_media` WHERE media_category = 'newsthumb' OR media_category = 'downloadthumb' LIMIT 1 "); - if($count ==1) - { - if ($just_check) return update_needed('Media-Manager Data needs to be updated.'); - $sql->update('core_media', "media_category='download_image' WHERE media_category = 'download' "); - $sql->update('core_media', "media_category='download_thumb' WHERE media_category = 'downloadthumb' "); - $sql->update('core_media', "media_category='news_thumb' WHERE media_category = 'newsthumb' "); - $log->addDebug("core-media Category names updated"); - } - - - // Media Update - core media and core-file. - /* - $count = $sql->gen("SELECT * FROM `#core_media` WHERE media_category = '_common' LIMIT 1 "); - if($count ==1) - { - if ($just_check) return update_needed('Media-Manager Category Data needs to be updated.'); - $sql->update('core_media', "media_category='_common_image' WHERE media_category = '_common' "); - $log->addDebug("core-media _common Category updated"); - } - */ - - - // Media Update - core media and core-file. CATEGORY - $count = $sql->gen("SELECT * FROM `#core_media_cat` WHERE media_cat_category = '_common' LIMIT 1 "); - if($count ==1) - { - if ($just_check) return update_needed('Media-Manager Category Data needs to be updated.'); - $sql->update('core_media_cat', "media_cat_category='_common_image' WHERE media_cat_category = '_common' "); - $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_file', '(Common Area)', 'Media in this category will be available in all areas of admin. ', 253, '', 0);"); - $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'download', 'download_file', 'Download Files', '', 253, '', 0);"); - $log->addDebug("core-media-cat _common Category updated"); - } - - $count = $sql->gen("SELECT * FROM `#core_media_cat` WHERE `media_cat_owner` = '_common' LIMIT 1 "); - - if($count != 1) - { - if ($just_check) return update_needed('Add Media-Manager Categories and Import existing images.'); - - $e107_core_media_cat = array( - array('media_cat_id'=>0,'media_cat_owner'=>'_common','media_cat_category'=>'_common_image','media_cat_title'=>'(Common Images)','media_cat_sef'=>'','media_cat_diz'=>'Media in this category will be available in all areas of admin.','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'0'), - array('media_cat_id'=>0,'media_cat_owner'=>'_common','media_cat_category'=>'_common_file','media_cat_title'=>'(Common Files)','media_cat_sef'=>'','media_cat_diz'=>'Media in this category will be available in all areas of admin.','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'0'), - array('media_cat_id'=>0,'media_cat_owner'=>'news','media_cat_category'=>'news','media_cat_title'=>'News','media_cat_sef'=>'','media_cat_diz'=>'Will be available in the news area.','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'1'), - array('media_cat_id'=>0,'media_cat_owner'=>'page','media_cat_category'=>'page','media_cat_title'=>'Custom Pages','media_cat_sef'=>'','media_cat_diz'=>'Will be available in the custom pages area of admin.','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'0'), - array('media_cat_id'=>0,'media_cat_owner'=>'download','media_cat_category'=>'download_image','media_cat_title'=>'Download Images','media_cat_sef'=>'','media_cat_diz'=>'','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'0'), - array('media_cat_id'=>0,'media_cat_owner'=>'download','media_cat_category'=>'download_thumb','media_cat_title'=>'Download Thumbnails','media_cat_sef'=>'','media_cat_diz'=>'','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'0'), - array('media_cat_id'=>0,'media_cat_owner'=>'download','media_cat_category'=>'download_file','media_cat_title'=>'Download Files','media_cat_sef'=>'','media_cat_diz'=>'','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'0'), - array('media_cat_id'=>0,'media_cat_owner'=>'news','media_cat_category'=>'news_thumb','media_cat_title'=>'News Thumbnails (Legacy)','media_cat_sef'=>'','media_cat_diz'=>'Legacy news thumbnails.','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'1'), - ); - - - foreach($e107_core_media_cat as $insert) - { - $sql->insert('core_media_cat', $insert); - } - - - - - // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_image', '(Common Images)', '', 'Media in this category will be available in all areas of admin. ', 253, '', 1);"); - // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_file', '(Common Files)', '', 'Media in this category will be available in all areas of admin. ', 253, '', 2);"); - - // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'news', 'news', 'News', '', 'Will be available in the news area. ', 253, '', 3);"); - // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'page', 'page', 'Custom Pages', '', 'Will be available in the custom pages area of admin. ', 253, '', 4);"); - - // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'download', 'download_image','', 'Download Images', '', 253, '', 5);"); - // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'download', 'download_thumb', '', 'Download Thumbnails', '', 253, '', 6);"); - // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'download', 'download_file', '', 'Download Files', '', 253, '', 7);"); - - // mysql_query("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'gallery', 'gallery_1', 'Gallery', 'Visible to the public at /gallery.php', 0, '', 0);"); - - // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'news', 'news_thumb', 'News Thumbnails (Legacy)', '', 'Legacy news thumbnails. ', 253, '', 8);"); - - $med->import('news_thumb', e_IMAGE.'newspost_images',"^thumb_"); - $med->import('news',e_IMAGE.'newspost_images'); - $med->import('page',e_IMAGE.'custom'); - - } - else - { -// $log->addDebug("Media COUNT was ".$count. " LINE: ".__LINE__); - } - - // Check for Legacy Download Images. - - $fl = e107::getFile(); - $dl_images = $fl->get_files(e_FILE.'downloadimages'); - - if(count($dl_images) && !$sql->gen("SELECT * FROM `#core_media` WHERE `media_category` = 'download_image' ")) - { - if ($just_check) return update_needed('Import Download Images into Media Manager'); - $med->import('download_image',e_FILE.'downloadimages'); - $med->import('download_thumb',e_FILE.'downloadthumbs'); - } - - $dl_files = $fl->get_files(e_FILE.'downloads', "","standard",5); // don't use e_DOWNLOAD or a loop may occur. - - - $publicFilter = array('_FT', '^thumbs\.db$','^Thumbs\.db$','.*\._$','^\.htaccess$','^\.cvsignore$','^\.ftpquota$','^index\.html$','^null\.txt$','\.bak$','^.tmp'); // Default file filter (regex format) -// $publicFilter = array(1); - $public_files = $fl->get_files(e_FILE.'public','',$publicFilter); - - if((count($dl_files) || count($public_files)) && !$sql->gen("SELECT * FROM `#core_media` WHERE `media_category` = 'download_file' OR `media_category` = '_common_file' ")) - { - if ($just_check) return update_needed('Import '.count($dl_files).' Download File(s) and '.count($public_files).' Public File(s) into Media Manager'); - - if($sql->gen("SELECT download_url FROM `#download` ")) - { - $allowed_types = array(); - - while($row = $sql->fetch()) - { - $ext = strrchr($row['download_url'], "."); - $suffix = ltrim($ext,"."); - - if(!isset($allowed_types[$suffix])) - { - $allowed_types[$suffix] = $suffix; - } - - } - - $allowed_types = array_unique($allowed_types); - } - else - { - $allowed_types = array('zip','gz','pdf'); - } - - $fmask = '[a-zA-Z0-9_.-]+\.('.implode('|',$allowed_types).')$'; - - $med->import('download_file',e_DOWNLOAD, $fmask); - - // add found Public file-types. - foreach($public_files as $v) - { - $ext = strrchr($v['fname'], "."); - $suffix = ltrim($ext,"."); - if(!isset($allowed_types[$suffix])) - { - $allowed_types[$suffix] = $suffix; - } - } - - $publicFmask = '[a-zA-Z0-9_.-]+\.('.implode('|',$allowed_types).')$'; - $med->import('_common_file', e_FILE.'public', $publicFmask); - } - - - - - $count = $sql->gen("SELECT * FROM `#core_media_cat` WHERE media_cat_owner='_icon' "); - - if(!$count) - { - if ($just_check) return update_needed('Add icons to media-manager'); - - $query = "INSERT INTO `".MPREFIX."core_media_cat` (`media_cat_id`, `media_cat_owner`, `media_cat_category`, `media_cat_title`, `media_cat_diz`, `media_cat_class`, `media_cat_image`, `media_cat_order`) VALUES - (0, '_icon', '_icon_16', 'Icons 16px', 'Available where icons are used in admin. ', 253, '', 0), - (0, '_icon', '_icon_32', 'Icons 32px', 'Available where icons are used in admin. ', 253, '', 0), - (0, '_icon', '_icon_48', 'Icons 48px', 'Available where icons are used in admin. ', 253, '', 0), - (0, '_icon', '_icon_64', 'Icons 64px', 'Available where icons are used in admin. ', 253, '', 0); - "; - - if(!$sql->gen($query)) - { - // echo "mysyql error"; - // error or already exists. - } - - $med->importIcons(e_PLUGIN); - $med->importIcons(e_IMAGE."icons/"); - $med->importIcons(e_THEME.$pref['sitetheme']."/images/"); - $log->addDebug("Icon category added"); - } - - // Search Clean up ---------------------------------- - - $searchPref = e107::getConfig('search'); - - if($searchPref->getPref('core_handlers/news')) - { - if ($just_check) return update_needed('Core search handlers need to be updated.'); - $searchPref->removePref('core_handlers/news')->save(false,true,false); - } - - if($searchPref->getPref('core_handlers/downloads')) - { - if ($just_check) return update_needed('Core search handlers need to be updated.'); - $searchPref->removePref('core_handlers/downloads')->save(false,true,false); - } - - if($searchPref->getPref('core_handlers/pages')) - { - if ($just_check) return update_needed('Core search handlers need to be updated.'); - $searchPref->removePref('core_handlers/pages')->save(false,true,false); - e107::getSingleton('e107plugin')->refresh('page'); - } - - // Clean up news keywords. - remove spaces between commas. - if($sql->select('news', 'news_id', "news_meta_keywords LIKE '%, %' LIMIT 1")) - { - if ($just_check) return update_needed('News keywords contain spaces between commas and needs to be updated. '); - $sql->update('news', "news_meta_keywords = REPLACE(news_meta_keywords, ', ', ',')"); - } - - - - - // Any other images should be imported manually via Media Manager batch-import. - - // ------------------------------------------------------------------ - - // Check that custompages have been imported from current theme.php file - - - - if (!$just_check) // Running the Upgrade Process. - { - - if(!is_array($pref['sitetheme_layouts']) || !vartrue($pref['sitetheme_deflayout'])) - { - $th = e107::getSingleton('themeHandler'); - $tmp = $th->getThemeInfo($pref['sitetheme']); - if($th->setTheme($pref['sitetheme'], false)) - { - $log->addDebug("Updated SiteTheme prefs"); - } - else - { - $log->addDebug("Couldn't update SiteTheme prefs"); - } - } - - $log->toFile('upgrade_v1_to_v2'); - - - if ($do_save) - { - // save_prefs(); - e107::getConfig()->setPref($pref)->save(false,true,false); - // $log->logMessage(LAN_UPDATE_50); - // $log->logMessage(implode(', ', $accum), E_MESSAGE_NODISPLAY); - //$updateMessages[] = LAN_UPDATE_50.implode(', ',$accum); // Note for admin log - } - - $log->flushMessages('UPDATE_01'); // Write admin log entry, update message handler - - } - else - { - $log->toFile('upgrade_v1_to_v2_check'); - - } - - - - - - - - //FIXME grab message-stack from $log for the log. - - //if ($just_check) return TRUE; - - - - - - //e107::getLog()->add('UPDATE_01',LAN_UPDATE_14.$e107info['e107_version'].'[!br!]'.implode('[!br!]',$updateMessages),E_LOG_INFORMATIVE,''); // Log result of actual update - return $just_check; -} - -/* No Longed Used I think -function core_media_import($cat,$epath) -{ - if(!vartrue($cat)){ return;} - - if(!is_readable($epath)) - { - return; - } - - $fl = e107::getFile(); - $tp = e107::getParser(); - $sql = e107::getDb(); - $mes = e107::getMessage(); - - $fl->setFileInfo('all'); - $img_array = $fl->get_files($epath,'','',2); - - if(!count($img_array)){ return;} - - foreach($img_array as $f) - { - $fullpath = $tp->createConstants($f['path'].$f['fname'],1); - - $insert = array( - 'media_caption' => $f['fname'], - 'media_description' => '', - 'media_category' => $cat, - 'media_datestamp' => $f['modified'], - 'media_url' => $fullpath, - 'media_userclass' => 0, - 'media_name' => $f['fname'], - 'media_author' => USERID, - 'media_size' => $f['fsize'], - 'media_dimensions' => $f['img-width']." x ".$f['img-height'], - 'media_usedby' => '', - 'media_tags' => '', - 'media_type' => $f['mime'] - ); - - if(!$sql->db_Select('core_media','media_url',"media_url = '".$fullpath."' LIMIT 1")) - { - if($sql->db_Insert("core_media",$insert)) - { - $mes->add("Importing Media: ".$f['fname'], E_MESSAGE_SUCCESS); - } - } - } -} -*/ - -function update_70x_to_706($type='') -{ - - global $sql,$ns, $pref, $e107info, $admin_log, $emessage; - - $just_check = $type == 'do' ? FALSE : TRUE; - if(!$sql->db_Field("plugin",5)) // not plugin_rss so just add the new one. - { - if ($just_check) return update_needed(); - $sql->gen("ALTER TABLE `".MPREFIX."plugin` ADD `plugin_addons` TEXT NOT NULL ;"); - catch_error($sql); - } - - //rename plugin_rss field - if($sql->db_Field("plugin",5) == "plugin_rss") - { - if ($just_check) return update_needed(); - $sql->gen("ALTER TABLE `".MPREFIX."plugin` CHANGE `plugin_rss` `plugin_addons` TEXT NOT NULL;"); - catch_error($sql); - } - - - if($sql->db_Field("dblog",5) == "dblog_query") - { - if ($just_check) return update_needed(); - $sql->gen("ALTER TABLE `".MPREFIX."dblog` CHANGE `dblog_query` `dblog_title` VARCHAR( 255 ) NOT NULL DEFAULT '';"); - catch_error($sql); - $sql->gen("ALTER TABLE `".MPREFIX."dblog` CHANGE `dblog_remarks` `dblog_remarks` TEXT NOT NULL;"); - catch_error($sql); - } - - if(!$sql->db_Field("plugin","plugin_path","UNIQUE")) - { - if ($just_check) return update_needed(); - if(!$sql->gen("ALTER TABLE `".MPREFIX."plugin` ADD UNIQUE (`plugin_path`);")) - { - $mesg = LAN_UPDATE_12." : ".ADLAN_145."."; - //$ns -> tablerender(LAN_ERROR,$mes); - $emessage->add($mesg, E_MESSAGE_ERROR); - catch_error($sql); - } - } - - if(!$sql->db_Field("online",6)) // online_active field - { - if ($just_check) return update_needed(); - $sql->gen("ALTER TABLE ".MPREFIX."online ADD online_active INT(10) UNSIGNED NOT NULL DEFAULT '0'"); - catch_error($sql); - } - - if ($sql -> db_Query("SHOW INDEX FROM ".MPREFIX."tmp")) - { - $row = $sql -> db_Fetch(); - if (!in_array('tmp_ip', $row)) - { - if ($just_check) return update_needed(); - $sql->gen("ALTER TABLE `".MPREFIX."tmp` ADD INDEX `tmp_ip` (`tmp_ip`);"); - $sql->gen("ALTER TABLE `".MPREFIX."upload` ADD INDEX `upload_active` (`upload_active`);"); - $sql->gen("ALTER TABLE `".MPREFIX."generic` ADD INDEX `gen_type` (`gen_type`);"); - } - } - - if (!$just_check) - { - // update new fields - require_once(e_HANDLER."plugin_class.php"); - $ep = new e107plugin; - $ep->update_plugins_table('update'); - $ep->save_addon_prefs('update'); - } - - if (!isset($pref['displayname_maxlength'])) - { - if ($just_check) return update_needed(); - $pref['displayname_maxlength'] = 15; - save_prefs(); - } - - - // If we get to here, in checking mode no updates are required. In update mode, all done. - if ($just_check) return TRUE; - e107::getLog()->add('UPDATE_02',LAN_UPDATE_14.$e107info['e107_version'],E_LOG_INFORMATIVE,''); // Log result of actual update - return $just_check; // TRUE if no updates needed, FALSE if updates needed and completed - -} - - - -/** - * Carries out the copy of timezone data from the user record to an extended user field - * @return boolean TRUE on success, FALSE on failure - */ -function copy_user_timezone() -{ - $sql = e107::getDb(); - $sql2 = e107::getDb('sql2'); - $tp = e107::getParser(); - - // require_once(e_HANDLER.'user_extended_class.php'); - $ue = e107::getUserExt(); - $tmp = $ue->parse_extended_xml('getfile'); - - $tmp['timezone']['parms'] = $tp->toDB($tmp['timezone']['parms']); - - if(!$ue->user_extended_add($tmp['timezone'])) - { - e107::getMessage()->addError("Unable to add user_timezone field to user_extended table."); - return false; - } - - if($sql->field('user_extended', 'user_timezone')===false) - { - e107::getMessage()->addError("user_timezone field missing from user_extended table."); - return false; - } - - e107::getMessage()->addDebug("Line:".__LINE__); - // Created the field - now copy existing data - if ($sql->db_Select('user','user_id, user_timezone')) - { - while ($row = $sql->db_Fetch()) - { - $sql2->update('user_extended',"`user_timezone`='{$row['user_timezone']}' WHERE `user_extended_id`={$row['user_id']}"); - } - } - return true; // All done! -} - - - - -function update_needed($message='') -{ - - if(E107_DEBUG_LEVEL) - { - $tmp = debug_backtrace(); - //$ns->tablerender("", "
Update required in ".basename(__FILE__)." on line ".$tmp[0]['line']."
"); - e107::getMessage()->add("Update required in ".basename(__FILE__)." on line ".$tmp[0]['line']." (".$message.")", E_MESSAGE_DEBUG); - } - return FALSE; -} - - - - -/** - * Add index to a table. Returns FALSE if not required. Returns a message if required and just checking - * - * @todo - get rid of $updateMessages parameter once log/message display method finalised, call the relevant method - */ -function addIndexToTable($target, $indexSpec, $just_check, &$updateMessages, $optionalTable=FALSE) -{ - global $sql; - if (!$sql->isTable($target)) - { - if ($optionalTable) - { - return !$just_check; // Nothing to do it table is optional and not there - } - $updateMessages[] = str_replace(array('[y]','[x]'),array($target,$indexSpec),LAN_UPDATE_54); - return !$just_check; // No point carrying on - return 'nothing to do' - } - if ($sql->gen("SHOW INDEX FROM ".MPREFIX.$target)) - { - $found = FALSE; - while ($row = $sql -> db_Fetch()) - { // One index per field - if (in_array($indexSpec, $row)) - { - return !$just_check; // Found - nothing to do - } - } - // Index not found here - if ($just_check) - { - return 'Required to add index to '.$target; - } - $sql->gen("ALTER TABLE `".MPREFIX.$target."` ADD INDEX `".$indexSpec."` (`".$indexSpec."`);"); - $updateMessages[] = str_replace(array('[y]','[x]'),array($target,$indexSpec),LAN_UPDATE_37); - } - return FALSE; -} - - -/** Check for database access errors - * @param reference $target - pointer to db object - * @return none - */ -function catch_error(&$target) -{ - if (vartrue($target->getLastErrorText()) && E107_DEBUG_LEVEL != 0) - { - $tmp2 = debug_backtrace(); - $tmp = $target->getLastErrorText(); - echo $tmp." [ ".basename(__FILE__)." on line ".$tmp2[0]['line']."]
"; - } - return; -} - - -function get_default_prefs() -{ - e107::getDebug()->log("Retrieving default prefs from xml file"); - $xmlArray = e107::getSingleton('xmlClass')->loadXMLfile(e_CORE."xml/default_install.xml",'advanced'); - $pref = e107::getSingleton('xmlClass')->e107ImportPrefs($xmlArray,'core'); - return $pref; -} - -function convert_serialized($serializedData, $type='') -{ - $arrayData = unserialize($serializedData); - $data = e107::serialize($arrayData,FALSE); - return $data; -} - -function theme_foot() -{ - global $pref; - - if(!empty($_POST['update_core']['706_to_800'])) - { - $data = array('name'=>SITENAME, 'theme'=>$pref['sitetheme'], 'language'=>e_LANGUAGE, 'url'=>SITEURL, 'type'=>'upgrade'); - $base = base64_encode(http_build_query($data, null, '&')); - $url = "https://e107.org/e-install/".$base; - return ""; - } - -} - -?> +retrieve_sys('nq_admin_updatecheck',3600, TRUE)) + { // See when we last checked for an admin update + list($last_time, $dont_check_update, $last_ver) = explode(',',$tempData); + if ($last_ver != $e107info['e107_version']) + { + $dont_check_update = FALSE; // Do proper check on version change + } + } +} +*/ + +$dont_check_update = false; + +if (!$dont_check_update) +{ + /* + if ($sql->db_Select('plugin', 'plugin_id, plugin_version, plugin_path', 'plugin_installflag=1')) + { + while ($row = $sql->db_Fetch()) + { // Mark plugins for update which have a specific update file, or a plugin.php file to check + if(is_readable(e_PLUGIN.$row['plugin_path'].'/'.$row['plugin_path'].'_update_check.php') || is_readable(e_PLUGIN.$row['plugin_path'].'/plugin.php') || is_readable(e_PLUGIN.$row['plugin_path'].'/'.$row['plugin_path'].'_setup.php')) + { + $dbupdateplugs[$row['plugin_path']] = $row['plugin_version']; + //TODO - Add support for {plugins}_setup.php upgrade check and routine. + } + } + } + */ + + if($dbupdateplugs = e107::getConfig('core')->get('plug_installed')) + { + // Read in each update file - this will add an entry to the $dbupdatep array if a potential update exists + foreach ($dbupdateplugs as $path => $ver) + { + if(!is_file(e_PLUGIN.$path."/plugin.xml")) + { + $fname = e_PLUGIN.$path.'/'.$path.'_update_check.php'; // DEPRECATED - left for BC only. + if (is_readable($fname)) include_once($fname); + } + + $fname = e_PLUGIN.$path.'/'.$path.'_setup.php'; + if (is_readable($fname)) + { + $dbupdatep[$path] = $path ; // ' 0.7.x forums '.LAN_UPDATE_9.' 0.8 forums'; + include_once($fname); + } + } + } + + + // List of potential updates + if (defined('TEST_UPDATE')) + { + $dbupdate['test_code'] = 'Test update routine'; + } + + // set 'master' to true to prevent other upgrades from running before it is complete. + + $LAN_UPDATE_4 = deftrue('LAN_UPDATE_4',"Update from [x] to [y]"); // in case language-pack hasn't been upgraded. + $LAN_UPDATE_5 = deftrue('LAN_UPDATE_5', "Core database structure"); + +// $dbupdate['218_to_219'] = array('master'=>false, 'title'=> e107::getParser()->lanVars($LAN_UPDATE_4, array('2.1.8','2.1.9')), 'message'=> null, 'hide_when_complete'=>true); + +// $dbupdate['217_to_218'] = array('master'=>false, 'title'=> e107::getParser()->lanVars($LAN_UPDATE_4, array('2.1.7','2.1.8')), 'message'=> null, 'hide_when_complete'=>true); + + $dbupdate['20x_to_220'] = array('master'=>false, 'title'=> e107::getParser()->lanVars($LAN_UPDATE_4, array('2.x','2.2.0')), 'message'=> null, 'hide_when_complete'=>false); + + $dbupdate['706_to_800'] = array('master'=>true, 'title'=> e107::getParser()->lanVars($LAN_UPDATE_4, array('1.x','2.0')), 'message'=> LAN_UPDATE_29, 'hide_when_complete'=>true); + + + // always run these last. + $dbupdate['core_database'] = array('master'=>false, 'title'=> $LAN_UPDATE_5); + $dbupdate['core_prefs'] = array('master'=>true, 'title'=> LAN_UPDATE_13); // Prefs check + + + +// $dbupdate['70x_to_706'] = LAN_UPDATE_8.' .70x '.LAN_UPDATE_9.' .706'; +} // End if (!$dont_check_update) + + + +// New in v2.x ------------------------------------------------ + +class e107Update +{ + var $core = array(); + var $updates = 0; + var $disabled = 0; + + + function __construct($core=null) + { + $mes = e107::getMessage(); + + $this->core = $core; + + if(varset($_POST['update_core']) && is_array($_POST['update_core'])) + { + $func = key($_POST['update_core']); + $this->updateCore($func); + } + + if(varset($_POST['update']) && is_array($_POST['update'])) // Do plugin updates + { + $func = key($_POST['update']); + $this->updatePlugin($func); + } + + // $dbv = e107::getSingleton('db_verify', e_HANDLER."db_verify_class.php"); + + // $dbv->clearCache(); + + + $this->renderForm(); + } + + + + + function updateCore($func='') + { + $mes = e107::getMessage(); + $tp = e107::getParser(); + $sql = e107::getDb(); + + + // foreach($this->core as $func => $data) + // { + if(function_exists('update_'.$func)) // Legacy Method. + { + $installed = call_user_func("update_".$func); + //?! (LAN_UPDATE == $_POST[$func]) + if(vartrue($_POST['update_core'][$func]) && !$installed) + { + if(function_exists("update_".$func)) + { + // $message = LAN_UPDATE_7." ".$func; + $message = $tp->lanVars(LAN_UPDATE_7, $this->core[$func]['title']); + $error = call_user_func("update_".$func, "do"); + + if($error != '') + { + $mes->add($message, E_MESSAGE_ERROR); + $mes->add($error, E_MESSAGE_ERROR); + } + else + { + $mes->add($message, E_MESSAGE_SUCCESS); + } + } + } + } + else + { + $mes->addDebug("could not run 'update_".$func); + } + + //} + + } + + + + function updatePlugin($path) + { + e107::getPlugin()->install_plugin_xml($path, 'upgrade'); + // e107::getPlugin()->save_addon_prefs(); // Rebuild addon prefs. + e107::getMessage()->reset(E_MESSAGE_INFO); + e107::getMessage()->addSuccess(LAN_UPDATED." : ".$path); + + } + + + + function plugins() + { + if(!$list = e107::getPlugin()->updateRequired()) + { + return false; + } + + $frm = e107::getForm(); + + $tp = e107::getParser(); + + $text = ""; + + uksort($list, "strnatcasecmp"); + + foreach($list as $path=>$val) + { + $name = !empty($val['@attributes']['lan']) ? $tp->toHTML($val['@attributes']['lan'],false,'TITLE') : $val['@attributes']['name']; + + $text .= " + ".$name." + ".$frm->admin_button('update['.$path.']', LAN_UPDATE, 'warning', '', 'disabled='.$this->disabled)." + "; + } + + return $text; + } + + + + + function core() + { + $frm = e107::getForm(); + $mes = e107::getMessage(); + $sql = e107::getDb(); + + $text = ""; + + + + foreach($this->core as $func => $data) + { + $text2 = ''; + + if(function_exists("update_".$func)) + { + + if(call_user_func("update_".$func)) + { + if(empty($data['hide_when_complete'])) + { + $text2 .= "".$data['title'].""; + $text2 .= "".ADMIN_TRUE_ICON.""; + } + } + else + { + $text2 .= "".$data['title'].""; + + if(vartrue($data['message'])) + { + $mes->addInfo($data['message']); + } + + $this->updates ++; + + $text2 .= "".$frm->admin_button('update_core['.$func.']', LAN_UPDATE, 'warning', '', "id=e-{$func}&disabled=".$this->disabled).""; + + if($data['master'] == true) + { + $this->disabled = 1; + } + } + + if(!empty($text2)) + { + $text .= "".$text2."\n"; + } + + } + } + + return $text; + } + + + + function renderForm() + { + $ns = e107::getRender(); + $mes = e107::getMessage(); + + $caption = LAN_UPDATE; + $text = " +
+
+ {$caption} + + + + + + + + + + + + + "; + + $text .= $this->core(); + $text .= $this->plugins(); + + $text .= " + +
".LAN_UPDATE_55."".LAN_UPDATE_2."
+
+
+ "; + + + $ns->tablerender(LAN_UPDATES,$mes->render() . $text); + + } + + +} + +/** + * Master routine to call to check for updates + */ +function update_check() +{ + + $ns = e107::getRender(); + $e107cache = e107::getCache(); + $sql = e107::getDb(); + $mes = e107::getMessage(); + + global $dont_check_update, $e107info; + global $dbupdate, $dbupdatep, $e107cache; + + $update_needed = FALSE; + + + + if ($dont_check_update === FALSE) + { + $dbUpdatesPref = array(); + + $skip = e107::getPref('db_updates'); + + foreach($dbupdate as $func => $rmks) // See which core functions need update + { + + if(!empty($skip[$func]) && (!deftrue('e_DEBUG') || E107_DBG_TIMEDETAILS)) // skip version checking when debug is off and check already done. + { + continue; + } + + if(function_exists('update_' . $func)) + { + + $sql->db_Mark_Time('Check Core Update_' . $func . ' '); + if(!call_user_func('update_' . $func, false)) + { + $dbUpdatesPref[$func] = 0; + $update_needed = true; + break; + } + elseif(strpos($func, 'core_') !==0) // skip the pref and table check. + { + $dbUpdatesPref[$func] = 1; + + } + } + + } + + e107::getConfig()->set('db_updates', $dbUpdatesPref)->save(false,true,false); + + + // Now check plugins - XXX DEPRECATED + foreach($dbupdatep as $func => $rmks) + { + if(function_exists('update_' . $func)) + { + // $sql->db_Mark_Time('Check Core Update_'.$func.' '); + if(!call_user_func('update_' . $func, false)) + { + $update_needed = true; + break; + } + } + } + + // New in v2.x + if(e107::getPlugin()->updateRequired('boolean')) + { + $update_needed = TRUE; + } + + + // $e107cache->set_sys('nq_admin_updatecheck', time().','.($update_needed ? '2,' : '1,').$e107info['e107_version'], TRUE); + } + else + { + $update_needed = ($dont_check_update == '2'); + } + + return $update_needed; +} + + +//XXX to be reworked eventually - for checking remote 'new versions' of plugins and installed theme. +// require_once(e_HANDLER.'e_upgrade_class.php'); +// $upg = new e_upgrade; + +// $upg->checkSiteTheme(); +// $upg->checkAllPlugins(); + + + +//-------------------------------------------- +// Check current prefs against latest list +//-------------------------------------------- +function update_core_prefs($type='') +{ + global $e107info; // $pref, $pref must be kept as global + + $pref = e107::getConfig('core', true, true)->getPref(); + $admin_log = e107::getAdminLog(); + $do_save = FALSE; + $should = get_default_prefs(); + + $just_check = $type == 'do' ? FALSE : TRUE; // TRUE if we're just seeing if an update is needed + + foreach ($should as $k => $v) + { + if ($k && !array_key_exists($k,$pref)) + { + if ($just_check) return update_needed('Missing pref: '.$k); + // $pref[$k] = $v; + e107::getConfig()->set($k,$v); + $admin_log->logMessage($k.' => '.$v, E_MESSAGE_NODISPLAY, E_MESSAGE_INFO); + $do_save = TRUE; + } + } + if ($do_save) + { + //save_prefs(); + e107::getConfig('core')->save(false,true); + $admin_log->logMessage(LAN_UPDATE_14.$e107info['e107_version'], E_MESSAGE_NODISPLAY, E_MESSAGE_INFO); + $admin_log->flushMessages('UPDATE_03',E_LOG_INFORMATIVE); + //e107::getLog()->add('UPDATE_03',LAN_UPDATE_14.$e107info['e107_version'].'[!br!]'.implode(', ',$accum),E_LOG_INFORMATIVE,''); // Log result of actual update + } + return $just_check; +} + + + +if (defined('TEST_UPDATE')) +{ +//-------------------------------------------- +// Test routine - to activate, define TEST_UPDATE +//-------------------------------------------- + function update_test_code($type='') + { + global $sql,$ns, $pref; + $just_check = $type == 'do' ? FALSE : TRUE; // TRUE if we're just seeing whether an update is needed + //--------------**************--------------- + // Add your test code in here + //--------------**************--------------- + + //--------------**************--------------- + // End of test code + //--------------**************--------------- + return $just_check; + } +} // End of test routine + +// generic database structure update. +function update_core_database($type = '') +{ + $just_check = ($type == 'do') ? FALSE : TRUE; +// require_once(e_HANDLER."db_verify_class.php"); +// $dbv = new db_verify; + + /** @var db_verify $dbv */ + $dbv = e107::getSingleton('db_verify', e_HANDLER."db_verify_class.php"); + + $log = e107::getAdminLog(); + + if($plugUpgradeReq = e107::getPlugin()->updateRequired()) + { + $exclude = array_keys($plugUpgradeReq); // search xxxxx_setup.php and check for 'upgrade_required()' == true. + asort($exclude); + } + else + { + $exclude = false; + } + + $dbv->compareAll($exclude); // core & plugins, but not plugins calling for an update with xxxxx_setup.php + + + if($dbv->errors()) + { + if ($just_check) + { + $mes = e107::getMessage(); + // $mes->addDebug(print_a($dbv->errors,true)); + $log->addDebug(print_a($dbv->errors,true)); + $tables = implode(", ", array_keys($dbv->errors)); + return update_needed("Database Tables require updating: ".$tables.""); + } + + $dbv->compileResults(); + $dbv->runFix(); // Fix entire core database structure and plugins too. + + + } + + + return $just_check; +} + +/* + function update_218_to_219($type='') + { + $sql = e107::getDb(); + $just_check = ($type == 'do') ? false : true; + + // add common video and audio media categories if missing. + $count = $sql->select("core_media_cat","*","media_cat_category = '_common_video' LIMIT 1 "); + + if(!$count) + { + if ($just_check) return update_needed('Media-Manager is missing the video and audio categories and needs to be updated.'); + + $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_video', '(Common Videos)', '', 'Media in this category will be available in all areas of admin. ', 253, '', 0);"); + $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_audio', '(Common Audio)', '', 'Media in this category will be available in all areas of admin. ', 253, '', 0);"); + } + + + + return $just_check; + }*/ + + + + + /** + * @param string $type + * @return bool true = no update required, and false if update required. + */ +/* function update_217_to_218($type='') + { + $just_check = ($type == 'do') ? false : true; + + $e_user_list = e107::getPref('e_user_list'); + + e107::getPlug()->clearCache()->buildAddonPrefLists(); + if(empty($e_user_list['user'])) // check e107_plugins/user/e_user.php is registered. + { + if($just_check) + { + return update_needed("user/e_user.php need to be registered"); // NO LAN. + } + + } + + + // Make sure, that the pref "post_script" contains one of the allowed userclasses + // Close possible security hole + if (!array_key_exists(e107::getPref('post_script'), e107::getUserClass()->uc_required_class_list('nobody,admin,main,classes,no-excludes', true))) + { + if ($just_check) + { + return update_needed("Pref 'Class which can post < script > and similar tags' contains an invalid value"); // NO LAN. + } + else + { + e107::getConfig()->setPref('post_script', 255)->save(false, true); + } + } + + + return $just_check; + + + + }*/ + + + + /** + * @param string $type + * @return bool true = no update required, and false if update required. + */ + function update_20x_to_220($type='') + { + + $sql = e107::getDb(); + $log = e107::getLog(); + $just_check = ($type == 'do') ? false : true; + $pref = e107::getPref(); + + + if(!$sql->select('core_media_cat', 'media_cat_id', "media_cat_category = '_icon_svg' LIMIT 1")) + { + if($just_check) + { + return update_needed("Missing Media-category for SVG"); + } + + $query = "INSERT INTO `#core_media_cat` (media_cat_id, media_cat_owner, media_cat_category, media_cat_title, media_cat_sef, media_cat_diz, media_cat_class, media_cat_image, media_cat_order) VALUES (NULL, '_icon', '_icon_svg', 'Icons SVG', '', 'Available where icons are used in admin.', '253', '', '0');"; + + $sql->gen($query); + + } + + + + if(isset($pref['e_header_list']['social'])) + { + if($just_check) + { + return update_needed("Social Plugin Needs to be refreshed. "); + } + + e107::getPlugin()->refresh('social'); + } + + + if(empty($pref['themecss'])) // FIX + { + if($just_check) + { + return update_needed("Theme CSS pref value is blank."); + } + + e107::getConfig()->set('themecss','style.css')->save(false,true,false); + } + + + // User is marked as not installed. + if($sql->select('plugin', 'plugin_id', "plugin_path = 'user' AND plugin_installflag != 1 LIMIT 1")) + { + if($just_check) + { + return update_needed("Plugin table 'user' value needs to be reset."); + } + + $sql->delete('plugin', "plugin_path = 'user'"); + + //e107::getPlug()->clearCache(); + } + + + // Make sure, that the pref "post_script" contains one of the allowed userclasses + // Close possible security hole + if (!array_key_exists(e107::getPref('post_script'), e107::getUserClass()->uc_required_class_list('nobody,admin,main,classes,no-excludes', true))) + { + if ($just_check) + { + return update_needed("Pref 'Class which can post < script > and similar tags' contains an invalid value"); // NO LAN. + } + else + { + e107::getConfig()->setPref('post_script', 255)->save(false, true); + } + } + + + // add common video and audio media categories if missing. + $count = $sql->select("core_media_cat","*","media_cat_category = '_common_video' LIMIT 1 "); + + if(!$count) + { + if ($just_check) return update_needed('Media-Manager is missing the video and audio categories and needs to be updated.'); + + $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_video', '(Common Videos)', '', 'Media in this category will be available in all areas of admin. ', 253, '', 0);"); + $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_audio', '(Common Audio)', '', 'Media in this category will be available in all areas of admin. ', 253, '', 0);"); + } + + + + return $just_check; + + + + + + } + + +//-------------------------------------------- +// Upgrade later versions of 0.7.x to 0.8 +//-------------------------------------------- +function update_706_to_800($type='') +{ + + global $pref, $e107info; + global $sysprefs, $eArrayStorage; + + //$mes = new messageLog; // Combined logging and message displaying handler + //$mes = e107::getMessage(); + $log = e107::getAdminLog(); // Used for combined logging and message displaying + $sql = e107::getDb(); + $sql2 = e107::getDb('sql2'); + $tp = e107::getParser(); + $ns = e107::getRender(); + + e107::getCache()->clearAll('db'); + e107::getCache()->clear_sys('Config'); + + e107::getMessage()->setUnique(); + + // List of unwanted $pref values which can go + $obs_prefs = array('frontpage_type','rss_feeds', 'log_lvcount', 'zone', 'upload_allowedfiletype', 'real', 'forum_user_customtitle', + 'utf-compatmode','frontpage_method','standards_mode','image_owner','im_quality', 'signup_option_timezone', + 'modules', 'plug_sc', 'plug_bb', 'plug_status', 'plug_latest', 'subnews_hide_news', 'upload_storagetype', + 'signup_remote_emailcheck' + + ); + + // List of DB tables not required (includes a few from 0.6xx) + $obs_tables = array('flood', 'stat_info', 'stat_counter', 'stat_last', 'session', 'preset', 'tinymce'); + + + // List of DB tables newly required (defined in core_sql.php) (The existing dblog table gets renamed) + // No Longer required. - automatically checked against core_sql.php. +// $new_tables = array('audit_log', 'dblog', 'news_rewrite', 'core_media', 'core_media_cat','cron', 'mail_recipients', 'mail_content'); + + // List of core prefs that need to be converted from serialized to e107ArrayStorage. + $serialized_prefs = array("'emote'", "'menu_pref'", "'search_prefs'", "'emote_default'", "'pm_prefs'"); + + + + + // List of changed DB tables (defined in core_sql.php) + // No Longer required. - automatically checked against core_sql.php. + // (primarily those which have changed significantly; for the odd field write some explicit code - it'll run faster) + // $changed_tables = array('user', 'dblog', 'admin_log', 'userclass_classes', 'banlist', 'menus', + // 'plugin', 'news', 'news_category', 'online', 'page', 'links', 'comments'); + + + // List of changed DB tables from core plugins (defined in pluginname_sql.php file) + // key = plugin directory name. Data = comma-separated list of tables to check + // (primarily those which have changed significantly; for the odd field write some explicit code - it'll run faster) + // No Longer required. - automatically checked by db-verify + /* $pluginChangedTables = array('linkwords' => 'linkwords', + 'featurebox' => 'featurebox', + 'links_page' => 'links_page', + 'poll' => 'polls', + 'content' => 'pcontent' + ); + + */ +/* + $setCorePrefs = array( //modified prefs during upgrade. + 'adminstyle' => 'infopanel', + 'admintheme' => 'bootstrap', + 'admincss' => 'admin_style.css', + 'resize_dimensions' => array( + 'news-image' => array('w' => 250, 'h' => 250), + 'news-bbcode' => array('w' => 250, 'h' => 250), + 'page-bbcode' => array('w' => 250, 'h' => 250) + ) + ); +*/ + + + + + $do_save = TRUE; + + + // List of changed menu locations. + $changeMenuPaths = array( + array('oldpath' => 'siteinfo_menu', 'newpath' => 'siteinfo', 'menu' => 'sitebutton_menu'), + array('oldpath' => 'siteinfo_menu', 'newpath' => 'siteinfo', 'menu' => 'compliance_menu'), + array('oldpath' => 'siteinfo_menu', 'newpath' => 'siteinfo', 'menu' => 'powered_by_menu'), + array('oldpath' => 'siteinfo_menu', 'newpath' => 'siteinfo', 'menu' => 'sitebutton_menu'), + array('oldpath' => 'siteinfo_menu', 'newpath' => 'siteinfo', 'menu' => 'counter_menu'), + array('oldpath' => 'siteinfo_menu', 'newpath' => 'siteinfo', 'menu' => 'latestnews_menu'), + array('oldpath' => 'compliance_menu', 'newpath' => 'siteinfo', 'menu' => 'compliance_menu'), + array('oldpath' => 'powered_by_menu', 'newpath' => 'siteinfo', 'menu' => 'powered_by_menu'), + array('oldpath' => 'sitebutton_menu', 'newpath' => 'siteinfo', 'menu' => 'sitebutton_menu'), + array('oldpath' => 'counter_menu', 'newpath' => 'siteinfo', 'menu' => 'counter_menu'), + array('oldpath' => 'usertheme_menu', 'newpath' => 'user', 'menu' => 'usertheme_menu'), + array('oldpath' => 'userlanguage_menu', 'newpath' => 'user', 'menu' => 'userlanguage_menu'), + array('oldpath' => 'lastseen_menu', 'newpath' => 'online', 'menu' => 'lastseen_menu'), + array('oldpath' => 'other_news_menu', 'newpath' => 'news', 'menu' => 'other_news_menu'), + array('oldpath' => 'other_news_menu', 'newpath' => 'news', 'menu' => 'other_news2_menu'), + array('oldpath' => 'user_menu', 'newpath' => 'user', 'menu' => 'usertheme_menu'), + array('oldpath' => 'user_menu', 'newpath' => 'user', 'menu' => 'userlanguage_menu'), + array('oldpath' => 'poll_menu', 'newpath' => 'poll', 'menu' => 'poll_menu'), + array('oldpath' => 'banner_menu', 'newpath' => 'banner', 'menu' => 'banner_menu'), + array('oldpath' => 'online_menu', 'newpath' => 'online', 'menu' => 'online_menu'), + ); + + + // List of DB tables (key) and field (value) which need changing to accommodate IPV6 addresses + $ip_upgrade = array('download_requests' => 'download_request_ip', + 'submitnews' => 'submitnews_ip', + 'tmp' => 'tmp_ip', + 'chatbox' => 'cb_ip' + ); + + $db_parser = new db_table_admin; // Class to read table defs and process them + $do_save = FALSE; // Set TRUE to update prefs when update complete + $updateMessages = array(); // Used to log actions for the admin log - TODO: will go once all converted to new class + + $just_check = ($type == 'do') ? FALSE : TRUE; // TRUE if we're just seeing whether an update is needed + +// if (!$just_check) +// { + // foreach(vartrue($setCorePrefs) as $k=>$v) + // { + // $pref[$k] = $v; + // } +// } + + if (!$just_check) + { + $log->logMessage(LAN_UPDATE_14.$e107info['e107_version'], E_MESSAGE_NODISPLAY); + } + + + + + + + + $statusTexts = array(E_MESSAGE_SUCCESS => 'Success', E_MESSAGE_ERROR => 'Fail', E_MESSAGE_INFO => 'Info'); + + + + if($pref['admintheme'] == 'bootstrap')//TODO Force an admin theme update or not? + { + if ($just_check) return update_needed('pref: Admin theme upgrade to bootstrap3 '); + + $pref['admintheme'] = 'bootstrap3'; + $pref['admincss'] = 'admin_dark.css'; + + $do_save = true; + } + + // convert all serialized core prefs to e107 ArrayStorage; + $serialz_qry = "SUBSTRING( e107_value,1,5)!='array' AND e107_value !='' "; + $serialz_qry .= "AND e107_name IN (".implode(",",$serialized_prefs).") "; + if(e107::getDb()->select("core", "*", $serialz_qry)) + { + if($just_check) return update_needed('Convert serialized core prefs'); + while ($row = e107::getDb()->fetch()) + { + + $status = e107::getDb('sql2')->update('core',"e107_value=\"".convert_serialized($row['e107_value'])."\" WHERE e107_name='".$row['e107_name']."'") ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR; + + $log->addDebug(LAN_UPDATE_22.$row['e107_name'].": ". $status); + } + } + + + if(e107::getDb()->select("core", "*", "e107_name='pm_prefs' LIMIT 1")) + { + if ($just_check) return update_needed('Rename the pm prefs'); + e107::getDb()->update("core", "e107_name='plugin_pm' WHERE e107_name = 'pm_prefs'"); + } + + + //@TODO de-serialize the user_prefs also. + + + // Banlist + + if(!$sql->field('banlist','banlist_id')) + { + if ($just_check) return update_needed('Banlist table requires updating.'); + $sql->gen("ALTER TABLE #banlist DROP PRIMARY KEY"); + $sql->gen("ALTER TABLE `#banlist` ADD `banlist_id` INT( 11 ) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST"); + } + + + + + + + // Move the maximum online counts from menu prefs to a separate pref - 'history' + e107::getCache()->clear_sys('Config'); + $menuConfig = e107::getConfig('menu',true,true); + + if ($menuConfig->get('most_members_online') || $menuConfig->get('most_guests_online') || $menuConfig->get('most_online_datestamp')) + { + $status = E_MESSAGE_DEBUG; + if ($just_check) return update_needed('Move online counts from menupref'); + $newPrefs = e107::getConfig('history'); + foreach (array('most_members_online', 'most_guests_online', 'most_online_datestamp') as $v) + { + if (FALSE === $newPrefs->get($v, FALSE)) + { + if (FALSE !== $menuConfig->get($v, FALSE)) + { + $newPrefs->set($v,$menuConfig->get($v)); + } + else + { + $newPrefs->set($v, 0); + } + } + $menuConfig->remove($v); + } + $result = $newPrefs->save(false, true, false); + if ($result === TRUE) + { + $resultMessage = 'Historic member counts updated'; + $result = $menuConfig->save(false, true, false); // Only re-save if successul. + } + elseif ($result === FALSE) + { + $resultMessage = 'moving historic member counts'; + $status = E_MESSAGE_ERROR; + } + else + { // No change + $resultMessage = 'Historic member counts already updated'; + $status = E_MESSAGE_INFO; + } + // $result = $menuConfig->save(false, true, false); // Save updated menuprefs - without the counts - don't delete them if it fails. + //$updateMessages[] = $statusTexts[$status].': '.$resultMessage; // Admin log message + $log->logMessage($resultMessage,$status); // User message + } + + + + // ++++++++ Modify Menu Paths +++++++. + if(varset($changeMenuPaths)) + { + foreach($changeMenuPaths as $val) + { + $qry = "SELECT menu_path FROM `#menus` WHERE menu_name = '".$val['menu']."' AND (menu_path='".$val['oldpath']."' || menu_path='".$val['oldpath']."/' ) LIMIT 1"; + if($sql->gen($qry)) + { + if ($just_check) return update_needed('Menu path changed required: '.$val['menu'].' '); + $updqry = "menu_path='".$val['newpath']."/' WHERE menu_name = '".$val['menu']."' AND (menu_path='".$val['oldpath']."' || menu_path='".$val['oldpath']."/' ) "; + $status = $sql->update('menus', $updqry) ? E_MESSAGE_DEBUG : E_MESSAGE_ERROR; + $log->logMessage(LAN_UPDATE_23.''.$val['menu'].' : '.$val['oldpath'].' => '.$val['newpath'], $status); // LAN_UPDATE_25; + // catch_error($sql); + } + } + } + + // Leave this one here.. just in case.. + //delete record for online_extended_menu (now only using one online menu) + if($sql->db_Select('menus', '*', "menu_path='online_extended_menu' || menu_path='online_extended_menu/'")) + { + if ($just_check) return update_needed("The Menu table needs to have some paths corrected in its data."); + + $row=$sql->db_Fetch(); + + //if online_extended is activated, we need to activate the new 'online' menu, and delete this record + if($row['menu_location']!=0) + { + $status = $sql->update('menus', "menu_name='online_menu', menu_path='online/' WHERE menu_path='online_extended_menu' || menu_path='online_extended_menu/' ") ? E_MESSAGE_DEBUG : E_MESSAGE_ERROR; + $log->logMessage(LAN_UPDATE_23."online_menu : online/", $status); + } + else + { //else if the menu is not active + //we need to delete the online_extended menu row, and change the online_menu to online + $sql->delete('menus', " menu_path='online_extended_menu' || menu_path='online_extended_menu/' "); + $log->logMessage(LAN_UPDATE_31, E_MESSAGE_DEBUG); + } + catch_error($sql); + } + + //change menu_path for online_menu (if it still exists) + if($sql->db_Select('menus', 'menu_path', "menu_path='online_menu' || menu_path='online_menu/'")) + { + if ($just_check) return update_needed('change menu_path for online menu'); + + $status = $sql->update('menus', "menu_path='online/' WHERE menu_path='online_menu' || menu_path='online_menu/' ") ? E_MESSAGE_DEBUG : E_MESSAGE_ERROR; + $log->logMessage(LAN_UPDATE_23."online_menu : online/", $status); + catch_error($sql); + } + + if (!$just_check) + { + // Alert Admin to delete deprecated menu folders. + $chgPath = array(); + foreach($changeMenuPaths as $cgpArray) + { + if(is_dir(e_PLUGIN.$cgpArray['oldpath'])) + { + if(!in_array($cgpArray['oldpath'],$chgPath)) + { + $chgPath[] = $cgpArray['oldpath']; + } + } + } + + if(count($chgPath)) + { + $log->addWarning(LAN_UPDATE_57.' '); + array_unique($chgPath); + asort($chgPath); + foreach($chgPath as $cgp) + { + $log->addWarning(e_PLUGIN_ABS."".$cgp.""); + } + } + + } + + + +//--------------------------------------------------------- +// Comments - split user field +//--------------------------------------------------------- + if($sql->db_Field('comments','comment_author')) + { + if ($just_check) return update_needed('Comment table author field update'); + + if ((!$sql->db_Field('comments','comment_author_id')) // Check to see whether new fields already added - maybe data copy failed part way through + && (!$sql->gen("ALTER TABLE `#comments` + ADD COLUMN comment_author_id int(10) unsigned NOT NULL default '0' AFTER `comment_author`, + ADD COLUMN comment_author_name varchar(100) NOT NULL default '' AFTER `comment_author_id`"))) + { + // Flag error + // $commentMessage = LAN_UPDAXXTE_34; + $log->logMessage(LAN_UPDATE_21."comments", E_MESSAGE_ERROR); + } + else + { + if (FALSE ===$sql->update('comments',"comment_author_id=SUBSTRING_INDEX(`comment_author`,'.',1), comment_author_name=SUBSTRING(`comment_author` FROM POSITION('.' IN `comment_author`)+1)")) + { + // Flag error + $log->logMessage(LAN_UPDATE_21.'comments', E_MESSAGE_ERROR); + } + else + { // Delete superceded field - comment_author + if (!$sql->gen("ALTER TABLE `#comments` DROP COLUMN `comment_author`")) + { + // Flag error + $log->logMessage(LAN_UPDATE_24.'comments - comment_author', E_MESSAGE_ERROR); + } + } + } + + $log->logMessage(LAN_UPDATE_21.'comments', E_MESSAGE_DEBUG); + } + + + + // Add index to download history + // Deprecated by db-verify-class + // if (FALSE !== ($temp = addIndexToTable('download_requests', 'download_request_datestamp', $just_check, $updateMessages))) + // { + // if ($just_check) + // { + // return update_needed($temp); + // } + // } + + // Extra index to tmp table + // Deprecated by db-verify-class + // if (FALSE !== ($temp = addIndexToTable('tmp', 'tmp_time', $just_check, $updateMessages))) + // { + // if ($just_check) + // { + // return update_needed($temp); + // } + // } + + // Extra index to rss table (if used) + // Deprecated by db-verify-class + // if (FALSE !== ($temp = addIndexToTable('rss', 'rss_name', $just_check, $updateMessages, TRUE))) + // { + // if ($just_check) + // { + // return update_needed($temp); + // } + // } + + // Front page prefs (logic has changed) + if (!isset($pref['frontpage_force'])) // Just set basic options; no real method of converting the existing + { + if ($just_check) return update_needed('Change front page prefs'); + $pref['frontpage_force'] = array(e_UC_PUBLIC => ''); + + $fpdef = vartrue($pref['frontpage']['all']) == 'index.php' ? 'index.php' : 'news.php'; + + $pref['frontpage'] = array(e_UC_PUBLIC => $fpdef); + // $_pdateMessages[] = LAN_UPDATE_38; //FIXME + $log->logMessage(LAN_UPDATE_20."frontpage",E_MESSAGE_DEBUG); + + e107::getConfig()->add('frontpage_force', $pref['frontpage_force']); + e107::getConfig()->add('frontpage', $pref['frontpage']); + unset($pref['frontpage_force'], $pref['frontpage']); + $do_save = TRUE; + } + + // Check need for user timezone before we delete the field +// if (vartrue($pref['signup_option_timezone'])) + { + if ($sql->field('user', 'user_timezone')===true && $sql->field('user_extended','user_timezone')===false) + { + if ($just_check) return update_needed('Move user timezone info'); + if (!copy_user_timezone()) + { // Error doing the transfer + //$updateMessages[] = LAN_UPDATE_42; + $log->logMessage(LAN_UPDATE_42, E_MESSAGE_ERROR); + return FALSE; + } + //$updateMessages[] = LAN_UPDATE_41; + $log->logMessage(LAN_UPDATE_41, E_MESSAGE_DEBUG); + } + } + + + // Tables defined in core_sql.php to be RENAMED. + + + // Next bit will be needed only by the brave souls who used an early CVS - probably delete before release + if ($sql->isTable('rl_history') && !$sql->isTable('dblog')) + { + if ($just_check) return update_needed('Rename rl_history to dblog'); + $sql->gen('ALTER TABLE `'.MPREFIX.'rl_history` RENAME `'.MPREFIX.'dblog`'); + //$updateMessages[] = LAN_UPDATE_44; + $log->logMessage(LAN_UPDATE_44, E_MESSAGE_DEBUG); + catch_error($sql); + } + + + + //--------------------------------- + if ($sql->isTable('dblog') && !$sql->isTable('admin_log')) + { + if ($just_check) return update_needed('Rename dblog to admin_log'); + $sql->gen('ALTER TABLE `'.MPREFIX.'dblog` RENAME `'.MPREFIX.'admin_log`'); + catch_error($sql); + //$updateMessages[] = LAN_UPDATE_43; + $log->logMessage(LAN_UPDATE_43, E_MESSAGE_DEBUG); + } + + + if($sql->isTable('forum_t') && $sql->isEmpty('forum') && $sql->isEmpty('forum_t')) + { + if ($just_check) return update_needed('Empty forum tables need to be removed.'); + $obs_tables[] = 'forum_t'; + $obs_tables[] = 'forum'; + + } + + + // Obsolete tables (list at top) + $sql->mySQLtableList = false; // clear the cached table list. + foreach ($obs_tables as $ot) + { + if ($sql->isTable($ot)) + { + if ($just_check) return update_needed("Delete table: ".$ot); + + $status = $sql->gen('DROP TABLE `'.MPREFIX.$ot.'`') ? E_MESSAGE_DEBUG : E_MESSAGE_ERROR; + $log->logMessage(LAN_UPDATE_25.$ot, $status); + } + } + + + // Tables where IP address field needs updating to accommodate IPV6 + // Set to varchar(45) - just in case something uses the IPV4 subnet (see http://en.wikipedia.org/wiki/IPV6#Notation) + foreach ($ip_upgrade as $t => $f) + { + if ($sql->isTable($t)) + { // Check for table - might add some core plugin tables in here + if ($field_info = ($sql->db_Field($t, $f, '', TRUE))) + { + if (strtolower($field_info['Type']) != 'varchar(45)') + { + if ($just_check) return update_needed('Update IP address field '.$f.' in table '.$t); + $status = $sql->gen("ALTER TABLE `".MPREFIX.$t."` MODIFY `{$f}` VARCHAR(45) NOT NULL DEFAULT '';") ? E_MESSAGE_DEBUG : E_MESSAGE_ERROR; + $log->logMessage(LAN_UPDATE_26.$t.' - '.$f, $status); + // catch_error($sql); + } + } + else + { + // Got a strange error here + } + } + } + + + + + + + + // Obsolete prefs (list at top) + // Intentionally do this last - we may check some of them during the update + $accum = array(); + foreach ($obs_prefs as $p) + { + if (isset($pref[$p])) + { + if ($just_check) return update_needed('Remove obsolete prefs'); + unset($pref[$p]); + e107::getConfig()->remove($p); + $do_save = true; + $log->addDebug('Removed obsolete pref: '.$p); + // $accum[] = $p; + } + } + + + + + + /* -------------- Upgrade Entire Table Structure - Multi-Language Supported ----------------- */ + // ONLY ever add fields, never deletes. + +// require_once(e_HANDLER."db_verify_class.php"); +// $dbv = new db_verify; + $dbv = e107::getSingleton('db_verify', e_HANDLER."db_verify_class.php"); + + if($plugUpgradeReq = e107::getPlugin()->updateRequired()) + { + $exclude = array_keys($plugUpgradeReq); // search xxxxx_setup.php and check for 'upgrade_required()' == true. + asort($exclude); + } + else + { + $exclude = false; + } + + $dbv->compareAll($exclude); // core & plugins, but not plugins calling for an update with xxxxx_setup.php + + if(count($dbv->errors)) + { + if ($just_check) + { + $mes = e107::getMessage(); + // $mes->addDebug(print_a($dbv->errors,true)); + $log->addDebug(print_a($dbv->errors,true)); + // return update_needed("Database Tables require updating."); // + } + else + { + $dbv->compileResults(); + $dbv->runFix(); // Fix entire core database structure and plugins too. + } + } + + // print_a($dbv->results); + // print_a($dbv->fixList); + + + //TODO - send notification messages to Log. + + + if($sql->field('page','page_theme') && $sql->gen("SELECT * FROM `#page` WHERE page_theme != '' AND menu_title = '' LIMIT 1")) + { + if ($just_check) + { + return update_needed("Pages/Menus Table requires updating."); + } + + if($sql->update('page',"menu_name = page_theme, menu_title = page_title, menu_text = page_text, menu_template='default', page_title = '', page_text = '' WHERE page_theme !='' AND menu_title = '' AND menu_text IS NULL ")) + { + $sql->gen("ALTER TABLE `#page` DROP page_theme "); + $mes = e107::getMessage(); + $log->addDebug("Successfully updated pages/menus table to new format. "); + } + else + { + $log->addDebug("FAILED to update pages/menus table to new format. "); + //$sql->gen("ALTER TABLE `#page` DROP page_theme "); + } + + } + + if($sql->field('plugin','plugin_releaseUrl')) + { + if ($just_check) return update_needed('plugin_releaseUrl is deprecated and needs to be removed. '); + if($sql->gen("ALTER TABLE `#plugin` DROP `plugin_releaseUrl`")) + { + $log->addDebug("Successfully removed plugin_releaseUrl. "); + } + + } + + + // --- Notify Prefs + +// $notify_prefs = $sysprefs -> get('notify_prefs'); +// $notify_prefs = $eArrayStorage -> ReadArray($notify_prefs); + e107::getCache()->clear_sys('Config'); + + $notify_prefs = e107::getConfig('notify',true,true)->getPref(); + + $nt_changed = 0; + if(vartrue($notify_prefs['event'])) + { + foreach ($notify_prefs['event'] as $e => $d) + { + if (isset($d['type'])) + { + if ($just_check) return update_needed('Notify pref: '.$e.' outdated'); + switch ($d['type']) + { + case 'main' : + $notify_prefs['event'][$e]['class'] = e_UC_MAINADMIN; + break; + case 'class' : // Should already have class defined + break; + case 'email' : + $notify_prefs['event'][$e]['class'] = 'email'; + break; + case 'off' : // Need to disable + default : + $notify_prefs['event'][$e]['class'] = e_UC_NOBODY; // Just disable if we don't know what else to do + } + $nt_changed++; + $notify_prefs['event'][$e]['legacy'] = 1; + unset($notify_prefs['event'][$e]['type']); + } + } + } + + if ($nt_changed) + { + $s_prefs = $tp -> toDB($notify_prefs); + $s_prefs = $eArrayStorage -> WriteArray($s_prefs); + // Could we use $sysprefs->set($s_prefs,'notify_prefs') instead - avoids caching problems ???? + $status = ($sql -> update("core", "e107_value='".$s_prefs."' WHERE e107_name='notify_prefs'") !== FALSE) ? E_MESSAGE_DEBUG : E_MESSAGE_ERROR; + $message = str_replace('[x]',$nt_changed,LAN_UPDATE_20); + $log->logMessage($message, $status); + } + + + + + if (isset($pref['forum_user_customtitle']) && !isset($pref['signup_option_customtitle'])) + { + if ($just_check) return update_needed('pref: forum_user_customtitle needs to be renamed'); + // $pref['signup_option_customtitle'] = $pref['forum_user_customtitle']; + e107::getConfig()->add('signup_option_customtitle', $pref['forum_user_customtitle']); + e107::getConfig()->remove('forum_user_customtitle'); + + $log->logMessage(LAN_UPDATE_20.'customtitle', E_MESSAGE_SUCCESS); + $do_save = TRUE; + } + + + // --------------- Saved emails - copy across + + if (!$just_check && $sql->select('generic', '*', "gen_type='massmail'")) + { + if ($just_check) return update_needed('Copy across saved emails'); + require_once(e_HANDLER.'mail_manager_class.php'); + $mailHandler = new e107MailManager; + $i = 0; + while ($row = $sql->fetch()) + { + $mailRecord = array( + 'mail_create_date' => $row['gen_datestamp'], + 'mail_creator' => $row['gen_user_id'], + 'mail_title' => $row['gen_ip'], + 'mail_subject' => $row['gen_ip'], + 'mail_body' => $row['gen_chardata'], + 'mail_content_status' => MAIL_STATUS_SAVED + ); + $mailHandler->mailtoDb($mailRecord, TRUE); + $mailHandler->saveEmail($mailRecord, TRUE); + $sql2->delete('generic', 'gen_id='.intval($row['gen_id'])); // Delete as we go in case operation fails part way through + $i++; + } + unset($mailHandler); + $log->logMessage(str_replace('[x]', $i, LAN_UPDATE_28)); + } + + + + + // ------------------- Populate Plugin Table With Changes ------------------ + + if (!isset($pref['shortcode_legacy_list'])) + { + if ($just_check) return update_needed('Legacy shortcode conversion'); + // Reset, legacy and new shortcode list will be generated in plugin update routine + // $pref['shortcode_legacy_list'] = array(); + // $pref['shortcode_list'] = array(); + + e107::getConfig()->add('shortcode_legacy_list', array()); + e107::getConfig()->set('shortcode_list', array()); + e107::getConfig()->save(false,true,false); + + $ep = e107::getPlugin(); + $ep->update_plugins_table($mode); // scan for e_xxx changes and save to plugin table. + $ep->save_addon_prefs($mode); // generate global e_xxx_list prefs from plugin table. + } + + + + // This has to be done after the table is upgraded + if($sql->select('plugin', 'plugin_category', "plugin_category = ''")) + { + if ($just_check) return update_needed('Update plugin table'); + require_once(e_HANDLER.'plugin_class.php'); + $ep = new e107plugin; + $ep->update_plugins_table('update'); + // $_pdateMessages[] = LAN_UPDATE_XX24; + // catch_error($sql); + } + + + //-- Media-manger import -------------------------------------------------- + + + + // Autogenerate filetypes.xml if not found. + if(!is_readable(e_SYSTEM."filetypes.xml")) + { + $data = ' + + +'; + + file_put_contents(e_SYSTEM."filetypes.xml",$data); + } + + + + $root_media = str_replace(basename(e_MEDIA)."/","",e_MEDIA); + $user_media_dirs = array("images","avatars", "avatars/default", "avatars/upload", "files","temp","videos","icons"); + + // check for old paths and rename. + if(is_dir($root_media."images") || is_dir($root_media."temp")) + { + foreach($user_media_dirs as $md) + { + @rename($root_media.$md,e_MEDIA.$md); + } + } + + // create sub-directories if they do not exist. + if(!is_dir(e_MEDIA."images") || !is_dir(e_MEDIA."temp") || !is_dir(e_AVATAR_UPLOAD) || !is_dir(e_AVATAR_DEFAULT) ) + { + foreach($user_media_dirs as $md) + { + if(!is_dir(e_MEDIA.$md)) + { + if(mkdir(e_MEDIA.$md)===false) + { + e107::getMessage()->addWarning("Unable to create ".e_MEDIA.$md."."); + } + } + } + } + + // Move Avatars to new location + $av1 = e107::getFile()->get_files(e_FILE.'public/avatars','.jpg|.gif|.png|.GIF|.jpeg|.JPG|.PNG'); + $av2 = e107::getFile()->get_files(e_IMAGE.'avatars','.jpg|.gif|.png|.GIF|.jpeg|.JPG|.PNG'); + + $avatar_images = array_merge($av1,$av2); + + if(count($avatar_images)) + { + if ($just_check) return update_needed('Avatar paths require updating.'); + foreach($avatar_images as $av) + { + $apath = (strstr($av['path'],'public/')) ? e_AVATAR_UPLOAD : e_AVATAR_DEFAULT; + + if(rename($av['path'].$av['fname'], $apath. $av['fname'])===false) + { + e107::getMessage()->addWarning("Unable to more ".$av['path'].$av['fname']." to ".$apath. $av['fname'].". Please move manually."); + } + } + } + + // ------------------------------- + + if (!e107::isInstalled('download') && $sql->gen("SELECT * FROM #links WHERE link_url LIKE 'download.php%' AND link_class != '".e_UC_NOBODY."' LIMIT 1")) + { + if ($just_check) return update_needed('Download Plugin needs to be installed.'); + // e107::getSingleton('e107plugin')->install('download',array('nolinks'=>true)); + e107::getSingleton('e107plugin')->refresh('download'); + } + + + + if (!e107::isInstalled('banner') && $sql->isTable('banner')) + { + if ($just_check) return update_needed('Banner Table found, but plugin not installed. Needs to be refreshed.'); + e107::getSingleton('e107plugin')->refresh('banner'); + } + + // --------------------------------- + + + $med = e107::getMedia(); + + // Media Category Update + if($sql->db_Field("core_media_cat","media_cat_nick")) + { + $count = $sql->gen("SELECT * FROM `#core_media_cat` WHERE media_cat_nick = '_common' "); + if($count ==1) + { + if ($just_check) return update_needed('Media-Manager Categories needs to be updated.'); + $sql->update('core_media_cat', "media_cat_owner = media_cat_nick, media_cat_category = media_cat_nick WHERE media_cat_nick REGEXP '_common|news|page|_icon_16|_icon_32|_icon_48|_icon_64' "); + $sql->update('core_media_cat', "media_cat_owner = '_icon', media_cat_category = media_cat_nick WHERE media_cat_nick REGEXP '_icon_16|_icon_32|_icon_48|_icon_64' "); + $sql->update('core_media_cat', "media_cat_owner = 'download', media_cat_category='download_image' WHERE media_cat_nick = 'download' "); + $sql->update('core_media_cat', "media_cat_owner = 'download', media_cat_category='download_thumb' WHERE media_cat_nick = 'downloadthumb' "); + $sql->update('core_media_cat', "media_cat_owner = 'news', media_cat_category='news_thumb' WHERE media_cat_nick = 'newsthumb' "); + $log->addDebug("core-media-cat Categories and Ownership updated"); + if($sql->gen("ALTER TABLE `".MPREFIX."core_media_cat` DROP `media_cat_nick`")) + { + $log->addDebug("core-media-cat `media_cat_nick` field removed."); + } + + // $query = "INSERT INTO `".MPREFIX."core_media_cat` (`media_cat_id`, `media_cat_owner`, `media_cat_category`, `media_cat_title`, `media_cat_diz`, `media_cat_class`, `media_cat_image`, `media_cat_order`) VALUES + // (0, 'gallery', 'gallery_1', 'Gallery 1', 'Visible to the public at /gallery.php', 0, '', 0); + /// "; + // + // if(mysql_query($query)) + // { + // $log->addDebug("Added core-media-cat Gallery."); + // } + } + } + + + // Media Update + $count = $sql->gen("SELECT * FROM `#core_media` WHERE media_category = 'newsthumb' OR media_category = 'downloadthumb' LIMIT 1 "); + if($count ==1) + { + if ($just_check) return update_needed('Media-Manager Data needs to be updated.'); + $sql->update('core_media', "media_category='download_image' WHERE media_category = 'download' "); + $sql->update('core_media', "media_category='download_thumb' WHERE media_category = 'downloadthumb' "); + $sql->update('core_media', "media_category='news_thumb' WHERE media_category = 'newsthumb' "); + $log->addDebug("core-media Category names updated"); + } + + + // Media Update - core media and core-file. + /* + $count = $sql->gen("SELECT * FROM `#core_media` WHERE media_category = '_common' LIMIT 1 "); + if($count ==1) + { + if ($just_check) return update_needed('Media-Manager Category Data needs to be updated.'); + $sql->update('core_media', "media_category='_common_image' WHERE media_category = '_common' "); + $log->addDebug("core-media _common Category updated"); + } + */ + + + // Media Update - core media and core-file. CATEGORY + $count = $sql->gen("SELECT * FROM `#core_media_cat` WHERE media_cat_category = '_common' LIMIT 1 "); + if($count ==1) + { + if ($just_check) return update_needed('Media-Manager Category Data needs to be updated.'); + $sql->update('core_media_cat', "media_cat_category='_common_image' WHERE media_cat_category = '_common' "); + $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_file', '(Common Area)', 'Media in this category will be available in all areas of admin. ', 253, '', 0);"); + $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'download', 'download_file', 'Download Files', '', 253, '', 0);"); + $log->addDebug("core-media-cat _common Category updated"); + } + + $count = $sql->gen("SELECT * FROM `#core_media_cat` WHERE `media_cat_owner` = '_common' LIMIT 1 "); + + if($count != 1) + { + if ($just_check) return update_needed('Add Media-Manager Categories and Import existing images.'); + + $e107_core_media_cat = array( + array('media_cat_id'=>0,'media_cat_owner'=>'_common','media_cat_category'=>'_common_image','media_cat_title'=>'(Common Images)','media_cat_sef'=>'','media_cat_diz'=>'Media in this category will be available in all areas of admin.','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'0'), + array('media_cat_id'=>0,'media_cat_owner'=>'_common','media_cat_category'=>'_common_file','media_cat_title'=>'(Common Files)','media_cat_sef'=>'','media_cat_diz'=>'Media in this category will be available in all areas of admin.','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'0'), + array('media_cat_id'=>0,'media_cat_owner'=>'news','media_cat_category'=>'news','media_cat_title'=>'News','media_cat_sef'=>'','media_cat_diz'=>'Will be available in the news area.','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'1'), + array('media_cat_id'=>0,'media_cat_owner'=>'page','media_cat_category'=>'page','media_cat_title'=>'Custom Pages','media_cat_sef'=>'','media_cat_diz'=>'Will be available in the custom pages area of admin.','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'0'), + array('media_cat_id'=>0,'media_cat_owner'=>'download','media_cat_category'=>'download_image','media_cat_title'=>'Download Images','media_cat_sef'=>'','media_cat_diz'=>'','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'0'), + array('media_cat_id'=>0,'media_cat_owner'=>'download','media_cat_category'=>'download_thumb','media_cat_title'=>'Download Thumbnails','media_cat_sef'=>'','media_cat_diz'=>'','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'0'), + array('media_cat_id'=>0,'media_cat_owner'=>'download','media_cat_category'=>'download_file','media_cat_title'=>'Download Files','media_cat_sef'=>'','media_cat_diz'=>'','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'0'), + array('media_cat_id'=>0,'media_cat_owner'=>'news','media_cat_category'=>'news_thumb','media_cat_title'=>'News Thumbnails (Legacy)','media_cat_sef'=>'','media_cat_diz'=>'Legacy news thumbnails.','media_cat_class'=>'253','media_cat_image'=>'','media_cat_order'=>'1'), + ); + + + foreach($e107_core_media_cat as $insert) + { + $sql->insert('core_media_cat', $insert); + } + + + + + // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_image', '(Common Images)', '', 'Media in this category will be available in all areas of admin. ', 253, '', 1);"); + // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, '_common', '_common_file', '(Common Files)', '', 'Media in this category will be available in all areas of admin. ', 253, '', 2);"); + + // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'news', 'news', 'News', '', 'Will be available in the news area. ', 253, '', 3);"); + // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'page', 'page', 'Custom Pages', '', 'Will be available in the custom pages area of admin. ', 253, '', 4);"); + + // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'download', 'download_image','', 'Download Images', '', 253, '', 5);"); + // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'download', 'download_thumb', '', 'Download Thumbnails', '', 253, '', 6);"); + // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'download', 'download_file', '', 'Download Files', '', 253, '', 7);"); + + // mysql_query("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'gallery', 'gallery_1', 'Gallery', 'Visible to the public at /gallery.php', 0, '', 0);"); + + // $sql->gen("INSERT INTO `".MPREFIX."core_media_cat` VALUES(0, 'news', 'news_thumb', 'News Thumbnails (Legacy)', '', 'Legacy news thumbnails. ', 253, '', 8);"); + + $med->import('news_thumb', e_IMAGE.'newspost_images',"^thumb_"); + $med->import('news',e_IMAGE.'newspost_images'); + $med->import('page',e_IMAGE.'custom'); + + } + else + { +// $log->addDebug("Media COUNT was ".$count. " LINE: ".__LINE__); + } + + // Check for Legacy Download Images. + + $fl = e107::getFile(); + $dl_images = $fl->get_files(e_FILE.'downloadimages'); + + if(count($dl_images) && !$sql->gen("SELECT * FROM `#core_media` WHERE `media_category` = 'download_image' ")) + { + if ($just_check) return update_needed('Import Download Images into Media Manager'); + $med->import('download_image',e_FILE.'downloadimages'); + $med->import('download_thumb',e_FILE.'downloadthumbs'); + } + + $dl_files = $fl->get_files(e_FILE.'downloads', "","standard",5); // don't use e_DOWNLOAD or a loop may occur. + + + $publicFilter = array('_FT', '^thumbs\.db$','^Thumbs\.db$','.*\._$','^\.htaccess$','^\.cvsignore$','^\.ftpquota$','^index\.html$','^null\.txt$','\.bak$','^.tmp'); // Default file filter (regex format) +// $publicFilter = array(1); + $public_files = $fl->get_files(e_FILE.'public','',$publicFilter); + + if((count($dl_files) || count($public_files)) && !$sql->gen("SELECT * FROM `#core_media` WHERE `media_category` = 'download_file' OR `media_category` = '_common_file' ")) + { + if ($just_check) return update_needed('Import '.count($dl_files).' Download File(s) and '.count($public_files).' Public File(s) into Media Manager'); + + if($sql->gen("SELECT download_url FROM `#download` ")) + { + $allowed_types = array(); + + while($row = $sql->fetch()) + { + $ext = strrchr($row['download_url'], "."); + $suffix = ltrim($ext,"."); + + if(!isset($allowed_types[$suffix])) + { + $allowed_types[$suffix] = $suffix; + } + + } + + $allowed_types = array_unique($allowed_types); + } + else + { + $allowed_types = array('zip','gz','pdf'); + } + + $fmask = '[a-zA-Z0-9_.-]+\.('.implode('|',$allowed_types).')$'; + + $med->import('download_file',e_DOWNLOAD, $fmask); + + // add found Public file-types. + foreach($public_files as $v) + { + $ext = strrchr($v['fname'], "."); + $suffix = ltrim($ext,"."); + if(!isset($allowed_types[$suffix])) + { + $allowed_types[$suffix] = $suffix; + } + } + + $publicFmask = '[a-zA-Z0-9_.-]+\.('.implode('|',$allowed_types).')$'; + $med->import('_common_file', e_FILE.'public', $publicFmask); + } + + + + + $count = $sql->gen("SELECT * FROM `#core_media_cat` WHERE media_cat_owner='_icon' "); + + if(!$count) + { + if ($just_check) return update_needed('Add icons to media-manager'); + + $query = "INSERT INTO `".MPREFIX."core_media_cat` (`media_cat_id`, `media_cat_owner`, `media_cat_category`, `media_cat_title`, `media_cat_diz`, `media_cat_class`, `media_cat_image`, `media_cat_order`) VALUES + (0, '_icon', '_icon_16', 'Icons 16px', 'Available where icons are used in admin. ', 253, '', 0), + (0, '_icon', '_icon_32', 'Icons 32px', 'Available where icons are used in admin. ', 253, '', 0), + (0, '_icon', '_icon_48', 'Icons 48px', 'Available where icons are used in admin. ', 253, '', 0), + (0, '_icon', '_icon_64', 'Icons 64px', 'Available where icons are used in admin. ', 253, '', 0); + "; + + if(!$sql->gen($query)) + { + // echo "mysyql error"; + // error or already exists. + } + + $med->importIcons(e_PLUGIN); + $med->importIcons(e_IMAGE."icons/"); + $med->importIcons(e_THEME.$pref['sitetheme']."/images/"); + $log->addDebug("Icon category added"); + } + + // Search Clean up ---------------------------------- + + $searchPref = e107::getConfig('search'); + + if($searchPref->getPref('core_handlers/news')) + { + if ($just_check) return update_needed('Core search handlers need to be updated.'); + $searchPref->removePref('core_handlers/news')->save(false,true,false); + } + + if($searchPref->getPref('core_handlers/downloads')) + { + if ($just_check) return update_needed('Core search handlers need to be updated.'); + $searchPref->removePref('core_handlers/downloads')->save(false,true,false); + } + + if($searchPref->getPref('core_handlers/pages')) + { + if ($just_check) return update_needed('Core search handlers need to be updated.'); + $searchPref->removePref('core_handlers/pages')->save(false,true,false); + e107::getSingleton('e107plugin')->refresh('page'); + } + + // Clean up news keywords. - remove spaces between commas. + if($sql->select('news', 'news_id', "news_meta_keywords LIKE '%, %' LIMIT 1")) + { + if ($just_check) return update_needed('News keywords contain spaces between commas and needs to be updated. '); + $sql->update('news', "news_meta_keywords = REPLACE(news_meta_keywords, ', ', ',')"); + } + + + + + // Any other images should be imported manually via Media Manager batch-import. + + // ------------------------------------------------------------------ + + // Check that custompages have been imported from current theme.php file + + + + if (!$just_check) // Running the Upgrade Process. + { + + if(!is_array($pref['sitetheme_layouts']) || !vartrue($pref['sitetheme_deflayout'])) + { + $th = e107::getSingleton('themeHandler'); + $tmp = $th->getThemeInfo($pref['sitetheme']); + if($th->setTheme($pref['sitetheme'], false)) + { + $log->addDebug("Updated SiteTheme prefs"); + } + else + { + $log->addDebug("Couldn't update SiteTheme prefs"); + } + } + + $log->toFile('upgrade_v1_to_v2'); + + + if ($do_save) + { + // save_prefs(); + e107::getConfig()->setPref($pref)->save(false,true,false); + // $log->logMessage(LAN_UPDATE_50); + // $log->logMessage(implode(', ', $accum), E_MESSAGE_NODISPLAY); + //$updateMessages[] = LAN_UPDATE_50.implode(', ',$accum); // Note for admin log + } + + $log->flushMessages('UPDATE_01'); // Write admin log entry, update message handler + + } + else + { + $log->toFile('upgrade_v1_to_v2_check'); + + } + + + + + + + + //FIXME grab message-stack from $log for the log. + + //if ($just_check) return TRUE; + + + + + + //e107::getLog()->add('UPDATE_01',LAN_UPDATE_14.$e107info['e107_version'].'[!br!]'.implode('[!br!]',$updateMessages),E_LOG_INFORMATIVE,''); // Log result of actual update + return $just_check; +} + +/* No Longed Used I think +function core_media_import($cat,$epath) +{ + if(!vartrue($cat)){ return;} + + if(!is_readable($epath)) + { + return; + } + + $fl = e107::getFile(); + $tp = e107::getParser(); + $sql = e107::getDb(); + $mes = e107::getMessage(); + + $fl->setFileInfo('all'); + $img_array = $fl->get_files($epath,'','',2); + + if(!count($img_array)){ return;} + + foreach($img_array as $f) + { + $fullpath = $tp->createConstants($f['path'].$f['fname'],1); + + $insert = array( + 'media_caption' => $f['fname'], + 'media_description' => '', + 'media_category' => $cat, + 'media_datestamp' => $f['modified'], + 'media_url' => $fullpath, + 'media_userclass' => 0, + 'media_name' => $f['fname'], + 'media_author' => USERID, + 'media_size' => $f['fsize'], + 'media_dimensions' => $f['img-width']." x ".$f['img-height'], + 'media_usedby' => '', + 'media_tags' => '', + 'media_type' => $f['mime'] + ); + + if(!$sql->db_Select('core_media','media_url',"media_url = '".$fullpath."' LIMIT 1")) + { + if($sql->db_Insert("core_media",$insert)) + { + $mes->add("Importing Media: ".$f['fname'], E_MESSAGE_SUCCESS); + } + } + } +} +*/ + +function update_70x_to_706($type='') +{ + + global $sql,$ns, $pref, $e107info, $admin_log, $emessage; + + $just_check = $type == 'do' ? FALSE : TRUE; + if(!$sql->db_Field("plugin",5)) // not plugin_rss so just add the new one. + { + if ($just_check) return update_needed(); + $sql->gen("ALTER TABLE `".MPREFIX."plugin` ADD `plugin_addons` TEXT NOT NULL ;"); + catch_error($sql); + } + + //rename plugin_rss field + if($sql->db_Field("plugin",5) == "plugin_rss") + { + if ($just_check) return update_needed(); + $sql->gen("ALTER TABLE `".MPREFIX."plugin` CHANGE `plugin_rss` `plugin_addons` TEXT NOT NULL;"); + catch_error($sql); + } + + + if($sql->db_Field("dblog",5) == "dblog_query") + { + if ($just_check) return update_needed(); + $sql->gen("ALTER TABLE `".MPREFIX."dblog` CHANGE `dblog_query` `dblog_title` VARCHAR( 255 ) NOT NULL DEFAULT '';"); + catch_error($sql); + $sql->gen("ALTER TABLE `".MPREFIX."dblog` CHANGE `dblog_remarks` `dblog_remarks` TEXT NOT NULL;"); + catch_error($sql); + } + + if(!$sql->db_Field("plugin","plugin_path","UNIQUE")) + { + if ($just_check) return update_needed(); + if(!$sql->gen("ALTER TABLE `".MPREFIX."plugin` ADD UNIQUE (`plugin_path`);")) + { + $mesg = LAN_UPDATE_12." : ".ADLAN_145."."; + //$ns -> tablerender(LAN_ERROR,$mes); + $emessage->add($mesg, E_MESSAGE_ERROR); + catch_error($sql); + } + } + + if(!$sql->db_Field("online",6)) // online_active field + { + if ($just_check) return update_needed(); + $sql->gen("ALTER TABLE ".MPREFIX."online ADD online_active INT(10) UNSIGNED NOT NULL DEFAULT '0'"); + catch_error($sql); + } + + if ($sql -> db_Query("SHOW INDEX FROM ".MPREFIX."tmp")) + { + $row = $sql -> db_Fetch(); + if (!in_array('tmp_ip', $row)) + { + if ($just_check) return update_needed(); + $sql->gen("ALTER TABLE `".MPREFIX."tmp` ADD INDEX `tmp_ip` (`tmp_ip`);"); + $sql->gen("ALTER TABLE `".MPREFIX."upload` ADD INDEX `upload_active` (`upload_active`);"); + $sql->gen("ALTER TABLE `".MPREFIX."generic` ADD INDEX `gen_type` (`gen_type`);"); + } + } + + if (!$just_check) + { + // update new fields + require_once(e_HANDLER."plugin_class.php"); + $ep = new e107plugin; + $ep->update_plugins_table('update'); + $ep->save_addon_prefs('update'); + } + + if (!isset($pref['displayname_maxlength'])) + { + if ($just_check) return update_needed(); + $pref['displayname_maxlength'] = 15; + save_prefs(); + } + + + // If we get to here, in checking mode no updates are required. In update mode, all done. + if ($just_check) return TRUE; + e107::getLog()->add('UPDATE_02',LAN_UPDATE_14.$e107info['e107_version'],E_LOG_INFORMATIVE,''); // Log result of actual update + return $just_check; // TRUE if no updates needed, FALSE if updates needed and completed + +} + + + +/** + * Carries out the copy of timezone data from the user record to an extended user field + * @return boolean TRUE on success, FALSE on failure + */ +function copy_user_timezone() +{ + $sql = e107::getDb(); + $sql2 = e107::getDb('sql2'); + $tp = e107::getParser(); + + // require_once(e_HANDLER.'user_extended_class.php'); + $ue = e107::getUserExt(); + $tmp = $ue->parse_extended_xml('getfile'); + + $tmp['timezone']['parms'] = $tp->toDB($tmp['timezone']['parms']); + + if(!$ue->user_extended_add($tmp['timezone'])) + { + e107::getMessage()->addError("Unable to add user_timezone field to user_extended table."); + return false; + } + + if($sql->field('user_extended', 'user_timezone')===false) + { + e107::getMessage()->addError("user_timezone field missing from user_extended table."); + return false; + } + + e107::getMessage()->addDebug("Line:".__LINE__); + // Created the field - now copy existing data + if ($sql->db_Select('user','user_id, user_timezone')) + { + while ($row = $sql->db_Fetch()) + { + $sql2->update('user_extended',"`user_timezone`='{$row['user_timezone']}' WHERE `user_extended_id`={$row['user_id']}"); + } + } + return true; // All done! +} + + + + +function update_needed($message='') +{ + + if(E107_DEBUG_LEVEL) + { + $tmp = debug_backtrace(); + //$ns->tablerender("", "
Update required in ".basename(__FILE__)." on line ".$tmp[0]['line']."
"); + e107::getMessage()->add("Update required in ".basename(__FILE__)." on line ".$tmp[0]['line']." (".$message.")", E_MESSAGE_DEBUG); + } + return FALSE; +} + + + + +/** + * Add index to a table. Returns FALSE if not required. Returns a message if required and just checking + * + * @todo - get rid of $updateMessages parameter once log/message display method finalised, call the relevant method + */ +function addIndexToTable($target, $indexSpec, $just_check, &$updateMessages, $optionalTable=FALSE) +{ + global $sql; + if (!$sql->isTable($target)) + { + if ($optionalTable) + { + return !$just_check; // Nothing to do it table is optional and not there + } + $updateMessages[] = str_replace(array('[y]','[x]'),array($target,$indexSpec),LAN_UPDATE_54); + return !$just_check; // No point carrying on - return 'nothing to do' + } + if ($sql->gen("SHOW INDEX FROM ".MPREFIX.$target)) + { + $found = FALSE; + while ($row = $sql -> db_Fetch()) + { // One index per field + if (in_array($indexSpec, $row)) + { + return !$just_check; // Found - nothing to do + } + } + // Index not found here + if ($just_check) + { + return 'Required to add index to '.$target; + } + $sql->gen("ALTER TABLE `".MPREFIX.$target."` ADD INDEX `".$indexSpec."` (`".$indexSpec."`);"); + $updateMessages[] = str_replace(array('[y]','[x]'),array($target,$indexSpec),LAN_UPDATE_37); + } + return FALSE; +} + + +/** Check for database access errors + * @param reference $target - pointer to db object + * @return none + */ +function catch_error(&$target) +{ + if (vartrue($target->getLastErrorText()) && E107_DEBUG_LEVEL != 0) + { + $tmp2 = debug_backtrace(); + $tmp = $target->getLastErrorText(); + echo $tmp." [ ".basename(__FILE__)." on line ".$tmp2[0]['line']."]
"; + } + return; +} + + +function get_default_prefs() +{ + e107::getDebug()->log("Retrieving default prefs from xml file"); + $xmlArray = e107::getSingleton('xmlClass')->loadXMLfile(e_CORE."xml/default_install.xml",'advanced'); + $pref = e107::getSingleton('xmlClass')->e107ImportPrefs($xmlArray,'core'); + return $pref; +} + +function convert_serialized($serializedData, $type='') +{ + $arrayData = unserialize($serializedData); + $data = e107::serialize($arrayData,FALSE); + return $data; +} + +function theme_foot() +{ + global $pref; + + if(!empty($_POST['update_core']['706_to_800'])) + { + $data = array('name'=>SITENAME, 'theme'=>$pref['sitetheme'], 'language'=>e_LANGUAGE, 'url'=>SITEURL, 'type'=>'upgrade'); + $base = base64_encode(http_build_query($data, null, '&')); + $url = "https://e107.org/e-install/".$base; + return ""; + } + +} + +?> diff --git a/e107_admin/users.php b/e107_admin/users.php index f66b39aa9..454674b3b 100644 --- a/e107_admin/users.php +++ b/e107_admin/users.php @@ -1,2999 +1,2999 @@ - array( - 'controller' => 'users_admin_ui', - 'path' => null, - 'ui' => 'users_admin_form_ui', - 'uipath' => null, - //'perm' => '0', - ), - 'ranks' => array( - 'controller' => 'users_ranks_ui', - 'path' => null, - 'ui' => 'users_ranks_ui_form', - 'uipath' => null, - //'perm' => '0', - ) - ); - - - protected $adminMenu = array( - 'main/list' => array('caption'=> LAN_MANAGE, 'perm' => '0|4'), - 'main/add' => array('caption'=> LAN_USER_QUICKADD, 'perm' => '4|U0|U1'), - 'main/prefs' => array('caption'=> LAN_OPTIONS, 'perm' => '4|U2'), - 'ranks/list' => array('caption'=> LAN_USER_RANKS, 'perm' => '4|U3'), - 'main/maintenance' => array('caption'=> LAN_MAINTENANCE, 'perm' => '4') - // 'ranks/list' => array('caption'=> LAN_USER_RANKS, 'perm' => '4|U3') - ); - - /* - FIXME - move user prune to Schedule tasks (cron) - $var ['prune']['text'] = LAN_USER_PRUNE; - $var ['prune']['link'] = e_ADMIN.'users.php?action=prune';// Will be moved to "Schedule tasks" - $var ['prune']['perm'] = '4'; - -*/ - protected $adminMenuAliases = array( - 'main/edit' => 'main/list', - 'main/admin' => 'main/list', - 'main/userclass'=> 'main/list', - 'main/test' => 'main/list', - ); - - protected $menuTitle = ADLAN_36; // 'Users' - - protected $adminMenuIcon = 'e-users-24'; - - - function init() - { - - $JS = <<'); // - - $(document).on('click', ".user-action", function(e){ - // e.stopPropagation(); - - var action = $(this).attr('data-action-type'); - var user = $(this).attr('data-action-user'); - - // $('#user-action-indicator-'+user).html(''); // - - $('.user-action-hidden').val(''); // clear all, incase of back-button or auto-fill. - $('#user-action-'+ user).val(action); - $('#core-user-list-form').submit(); - - - }); -JS; - - e107::js('footer-inline', $JS); - e107::css('inline', ' - .user-action { cursor: pointer } - .btn-user-action { margin-right:15px} - - '); - - } - - /** - * Run observers/headers override - * - * @return users_admin - */ - public function runObservers($run_header = true) - { - // Catch useraction - if (isset($_POST['useraction'])) - { - if(is_array($_POST['useraction'])) - { - foreach ($_POST['useraction'] as $key => $val) - { - if ($val) - { - $_POST['useraction'] = $val; - $_POST['userip'] = $_POST['userip'][$key]; - $_POST['userid'] = (int) $key; - break; - } - } - } - - // FIXME IMPORTANT - permissions per action/trigger - - // map useraction to UI trigger - switch ($_POST['useraction']) - { - ### etrigger_delete - case 'deluser': - if($_POST['userid']) - { - $id = (int) $_POST['userid']; - $_POST['etrigger_delete'] = array($id => $id); - $user = e107::getDb()->retrieve('user', 'user_email, user_name', 'user_id='.$id); - $rplc_from = array('[x]', '[y]', '[z]'); - $rplc_to = array($user['user_name'], $user['user_email'], $id); - $message = str_replace($rplc_from, $rplc_to, USRLAN_222); - $this->getController()->deleteConfirmMessage = $message; - } - break; - - // map to List{USERACTION}Trigger() - case 'unban': - case 'ban': - case 'verify': - case 'reqverify': - case 'resend': - case 'loginas': - case 'unadmin': - $_POST['etrigger_'.$_POST['useraction']] = intval($_POST['userid']); - break; - - - case 'logoutas': - $this->getRequest() - ->setQuery(array()) - ->setMode('main') - ->setAction('logoutas'); - break; - - // redirect to AdminObserver/AdminPage() - case 'admin': - case 'adminperms': - $this->getRequest() - ->setQuery(array()) - ->setMode('main') - ->setAction('admin') - ->setId($_POST['userid']); - - $this->getController()->redirect(); - break; - - // redirect to UserclassObserver/UserclassPage() - case 'userclass': - $this->getRequest() - ->setQuery(array()) - ->setMode('main') - ->setAction('userclass') - ->setId($_POST['userid']); - - $this->getController()->redirect(); - break; - - // redirect to TestObserver/TestPage - case 'test': - $this->getRequest() - ->setQuery(array()) - ->setMode('main') - ->setAction('test') - ->setId($_POST['userid']); - - $this->getController()->redirect(); - break; - - // redirect to TestObserver/TestPage - case 'usersettings': - $this->getRequest() - ->setQuery(array()) - ->setMode('main') - ->setAction('edit') - ->setId($_POST['userid']); - $this->getController()->redirect(); - - - //XXX Broken to the point of being unusable. //header('location:'.e107::getUrl()->create('user/profile/edit', 'id='.(int) $_POST['userid'], 'full=1&encode=0')); - // exit; - break; - } - - } - - return parent::runObservers($run_header); - } -} - - -class users_admin_ui extends e_admin_ui -{ - - protected $pluginTitle = ADLAN_36; - protected $pluginName = 'core'; - protected $eventName = 'user'; - protected $table = "user"; - -// protected $listQry = "SELECT SQL_CALC_FOUND_ROWS * FROM #users"; // without any Order or Limit. - protected $listQry = "SELECT SQL_CALC_FOUND_ROWS u.*,ue.* from #user AS u LEFT JOIN #user_extended AS ue ON u.user_id = ue.user_extended_id "; // without any Order or Limit. - - protected $editQry = "SELECT u.*,ue.* FROM #user AS u left join #user_extended AS ue ON u.user_id = ue.user_extended_id WHERE user_id = {ID}"; - - protected $pid = "user_id"; - protected $perPage = 10; - protected $batchDelete = true; - protected $listOrder = 'user_id DESC'; - - /** - * Show confirm screen before (batch/single) delete - * @var boolean - */ - public $deleteConfirmScreen = true; - - /** - * @var boolean - */ - protected $batchCopy = false; - - /** - * List (numerical array) of only disallowed for this controller actions - */ - protected $disallow = array('create'); - - protected $tabs = array(LAN_BASIC, LAN_EXTENDED); - - protected $url = array( - 'route'=>'user/profile/view', - 'name' => 'user_name', - 'description' => 'user_name', - 'vars'=> array('user_id' => true, 'user_name' => true) - ); - - //TODO - finish 'user' type, set 'data' to all editable fields, set 'noedit' for all non-editable fields - protected $fields = array( - 'checkboxes' => array('title'=> '', 'type' => null, 'width' =>'5%', 'forced'=> TRUE, 'thclass'=>'center', 'class'=>'center'), - - 'user_id' => array('title' => LAN_ID, 'tab'=>0, 'type' =>'text', 'data'=>'int', 'width' => '5%','forced' => true, 'readParms'=>'link=sef&target=blank'), -// 'user_status' => array('title' => LAN_STATUS, 'type' => 'method', 'alias'=>'user_status', 'width' => 'auto','forced' => true, 'nosort'=>TRUE), - 'user_ban' => array('title' => LAN_STATUS, 'tab'=>0, 'type' => 'method', 'width' => 'auto', 'filter'=>true, 'batch'=>true,'thclass'=>'center', 'class'=>'center'), - - 'user_name' => array('title' => LAN_USER_01, 'tab'=>0, 'type' => 'text', 'inline'=>true, 'data'=>'safestr', 'width' => 'auto','thclass' => 'left first'), // Display name - 'user_loginname' => array('title' => LAN_USER_02, 'tab'=>0, 'type' => 'text', 'data'=>'safestr', 'width' => 'auto'), // User name - 'user_login' => array('title' => LAN_USER_03, 'tab'=>0, 'type' => 'text', 'inline'=>true, 'data'=>'safestr', 'width' => 'auto'), // Real name (no real vetting) - 'user_customtitle' => array('title' => LAN_USER_04, 'tab'=>0, 'type' => 'text', 'inline'=>true, 'data'=>'safestr', 'width' => 'auto'), // No real vetting - 'user_password' => array('title' => LAN_PASSWORD, 'tab'=>0, 'type' => 'method', 'data'=>'safestr', 'width' => 'auto'), //TODO add md5 option to form handler? - 'user_sess' => array('title' => LAN_SESSION, 'tab'=>0, 'noedit'=>true, 'type' => 'text', 'width' => 'auto'), // Photo - 'user_image' => array('title' => LAN_USER_07, 'tab'=>0, 'type' => 'dropdown', 'data'=>'str', 'width' => 'auto'), // Avatar - 'user_email' => array('title' => LAN_EMAIL, 'tab'=>0, 'type' => 'text', 'inline'=>true, 'data'=>'safestr', 'width' => 'auto', 'writeParms'=>array('size'=>'xxlarge')), - 'user_hideemail' => array('title' => LAN_USER_10, 'tab'=>0, 'type' => 'boolean', 'data'=>'int', 'width' => 'auto', 'thclass'=>'center', 'class'=>'center', 'filter'=>true, 'batch'=>true, 'readParms'=>'trueonly=1'), - 'user_xup' => array('title' => 'Xup', 'tab'=>0, 'noedit'=>true, 'type' => 'text', 'data'=>'str', 'width' => 'auto'), - 'user_class' => array('title' => LAN_USER_12, 'tab'=>0, 'type' => 'userclasses' , 'data'=>'safestr', 'inline'=>true, 'writeParms' => 'classlist=classes,new', 'readParms'=>'classlist=classes,new&defaultLabel=--', 'filter'=>true, 'batch'=>true), - 'user_join' => array('title' => LAN_USER_14, 'tab'=>0, 'noedit'=>true, 'type' => 'datestamp', 'width' => 'auto', 'writeParms'=>'readonly=1'), - 'user_lastvisit' => array('title' => LAN_USER_15, 'tab'=>0, 'noedit'=>true, 'type' => 'datestamp', 'width' => 'auto'), - 'user_currentvisit' => array('title' => LAN_USER_16, 'tab'=>0, 'noedit'=>true, 'type' => 'datestamp', 'width' => 'auto'), - 'user_comments' => array('title' => LAN_COMMENTS, 'tab'=>0, 'noedit'=>true, 'type' => 'int', 'width' => 'auto','thclass'=>'right','class'=>'right'), - 'user_lastpost' => array('title' => USRLAN_195, 'tab'=>0, 'noedit'=>true, 'type' => 'datestamp', 'width' => 'auto'), - 'user_ip' => array('title' => LAN_USER_18, 'tab'=>0, 'noedit'=>true, 'type' => 'ip', 'data'=>'str', 'width' => 'auto'), - // 'user_prefs' => array('title' => LAN_USER_20, 'type' => 'text', 'width' => 'auto'), - 'user_visits' => array('title' => LAN_USER_21, 'tab'=>0, 'noedit'=>true, 'type' => 'int', 'width' => 'auto','thclass'=>'right','class'=>'right'), - 'user_admin' => array('title' => LAN_USER_22, 'tab'=>0, 'type' => 'method', 'width' => 'auto', 'thclass'=>'center', 'class'=>'center', 'filter'=>true, 'batch'=>true, 'readParms'=>'trueonly=1'), - 'user_perms' => array('title' => LAN_USER_23, 'tab'=>0, 'type' => 'method', 'data'=>'str', 'width' => 'auto'), - 'user_pwchange' => array('title' => LAN_USER_24, 'tab'=>0, 'noedit'=>true, 'type'=>'datestamp' , 'width' => 'auto'), - - ); - - protected $fieldpref = array('user_ban','user_name','user_loginname','user_login','user_email','user_class','user_admin'); - - protected $prefs = array( - // 'anon_post' => array('title'=>PRFLAN_32, 'type'=>'boolean'), - 'avatar_upload' => array('title' => USRLAN_44, 'type' => 'boolean', 'writeParms' => 'label=yesno', 'data' => 'int',), - 'photo_upload' => array('title' => USRLAN_53, 'type' => 'boolean', 'writeParms' => 'label=yesno', 'data' => 'int',), - 'im_width' => array('title' => USRLAN_47, 'type' => 'number', 'writeParms' => array('maxlength' => 4), 'help' => USRLAN_48, 'data' => 'int', ), - 'im_height' => array('title' => USRLAN_49, 'type' => 'number', 'writeParms' => array('maxlength' => 4), 'help' => USRLAN_50, 'data' => 'int', ), - 'profile_rate' => array('title' => USRLAN_126, 'type' => 'boolean', 'writeParms' => 'label=yesno', 'data' => 'int',), - 'profile_comments' => array('title' => USRLAN_127, 'type' => 'boolean', 'writeParms' => 'label=yesno', 'data' => 'int',), - 'force_userupdate' => array('title' => USRLAN_133, 'type' => 'boolean', 'writeParms' => 'label=yesno', 'help' => USRLAN_134, 'data' => 'int',), - 'del_unv' => array('title' => USRLAN_93, 'type' => 'number', 'writeParms' => array('maxlength' => 5, 'post' => USRLAN_95), 'help' => USRLAN_94, 'data' => 'int',), - 'track_online' => array('title' => USRLAN_130, 'type' => 'boolean', 'writeParms' => 'label=yesno', 'help' => USRLAN_131, 'data' => 'int',), - 'memberlist_access' => array('title' => USRLAN_146, 'type' => 'userclass', 'writeParms' => 'classlist=public,member,guest,admin,main,classes,nobody', 'data' => 'int',), - 'signature_access' => array('title' => USRLAN_194, 'type' => 'userclass', 'writeParms' => 'classlist=member,admin,main,classes,nobody', 'data' => 'int',), - 'user_new_period' => array('title' => USRLAN_190, 'type' => 'number', 'writeParms' => array('maxlength' => 3, 'post' => LANDT_04s), 'help' => USRLAN_191, 'data' => 'int',), - ); - - public $extended = array(); - public $extendedData = array(); - - - - function getExtended() - { - return $this->extendedData; - } - - function init() - { - - $sql = e107::getDb(); - $tp = e107::getParser(); - - - if(!empty($_POST['resendToAll'])) - { - $resetPasswords = !empty($_POST['resetPasswords']); - $age = vartrue($_POST['resendAge'], 24); - $class = vartrue($_POST['resendClass'], false); - $this->resend_to_all($resetPasswords, $age, $class); - } - - - if($this->getAction() == 'edit') - { - $this->fields['user_class']['noedit'] = true; - } - - - - - - - - // Extended fields - FIXME - better field types - - if($rows = $sql->retrieve('user_extended_struct', '*', "user_extended_struct_type > 0 AND user_extended_struct_text != '_system_' ORDER BY user_extended_struct_parent ASC",true)) - { - // TODO FIXME use the handler to build fields and field attributes - // FIXME a way to load 3rd party language files for extended user fields - e107::coreLan('user_extended'); - - $dataMode = ($this->getAction() === 'list') ? 'str' : false; // allow for search of extended fields. - - foreach ($rows as $row) - { - $field = "user_".$row['user_extended_struct_name']; - // $title = ucfirst(str_replace("user_","",$field)); - $label = $tp->toHTML($row['user_extended_struct_text'],false,'defs'); - $this->fields[$field] = array('__tableField'=>'ue.'.$field, 'title' => $label,'width' => 'auto', 'type'=>'method', 'readParms'=>array('ueType'=>$row['user_extended_struct_type']), 'method'=>'user_extended', 'data'=>$dataMode, 'tab'=>1, 'noedit'=>false); - - $this->extended[] = $field; - $this->extendedData[$field] = $row; - } - } - - - if(empty($this->extended)) - { - $this->tabs = false; - } - - - - $this->fields['user_signature']['writeParms']['data'] = e107::getUserClass()->uc_required_class_list("classes"); - - $this->fields['user_signature'] = array('title' => LAN_USER_09, 'type' => 'textarea', 'data'=>'str', 'width' => 'auto', 'writeParms'=>array('size'=>'xxlarge')); - $this->fields['options'] = array('title'=> LAN_OPTIONS." ", 'type' => 'method', 'forced'=>TRUE, 'width' => '10%', 'thclass' => 'right last', 'class' => 'left'); - - - if(!getperms('4|U0')) // Quick Add User Access Only. - { - unset($this->fields['checkboxes']); - unset($this->fields['options']); - } - - $this->fields['user_image']['writeParms'] = $this->getAvatarList(); - - if(!empty($_GET['readonly'])) - { - foreach($this->fields as $key=>$v) - { - if($key == 'options' || $key == 'checkboxes') - { - continue; - } - - $this->fields[$key]['readonly'] = 2; - - } - } - // print_a($this->fields); - if(!empty($_GET['iframe'])) - { - define('e_IFRAME', true); - } - - - - } - - - - protected function getAvatarList() - { - $avs = array(''=>LAN_NONE); - $upload = array(); - $sys = array(); - $uploaded = e107::getFile()->get_files(e_AVATAR_UPLOAD); - foreach($uploaded as $f) - { - $id = '-upload-'.$f['fname']; - $upload[$id] = $f['fname']; - } - $system = e107::getFile()->get_files(e_AVATAR_DEFAULT); - foreach($system as $f) - { - $id = $f['fname']; - $sys[$id] = $f['fname']; - } - - $avs['uploaded'] = $upload; - $avs['system'] = $sys; - - return $avs; - } - - - public function afterDelete($deletedData, $id=null, $deleted_check) - { - if(!empty($id)) - { - $sql = e107::getDb(); - $sql->delete('user_extended',"user_extended_id = ".$id); - - e107::getCache()->clear('online_menu_member_newest'); - e107::getCache()->clear('online_menu_member_total'); - } - - } - - - - - public function beforeUpdate($new_data, $old_data, $id) - { - $tp = e107::getParser(); - - $pwdField = 'user_password_'.$id; - - if(!empty($new_data[$pwdField])) - { - $new_data['user_password'] = $new_data[$pwdField]; - unset($new_data[$pwdField]); - } - - // e107::getMessage()->addInfo(print_a($new_data,true)); - - if(empty($new_data['user_password'])) - { - $new_data['user_password'] = $old_data['user_password']; - } - else - { - - // issues #3126, #3143: Login not working after admin set a new password using the backend - // Backend used user_login instead of user_loginname (used in usersettings) and did't escape the password. - $savePassword = $new_data['user_password']; - $loginname = $new_data['user_loginname'] ? $new_data['user_loginname'] : $old_data['user_loginname']; - $email = (isset($new_data['user_email']) && $new_data['user_email']) ? $new_data['user_email'] : $old_data['user_email']; - $new_data['user_password'] = e107::getDb()->escape(e107::getUserSession()->HashPassword($savePassword, $loginname), false); - - e107::getMessage()->addDebug("Password Hash: ".$new_data['user_password']); - } - - if(!empty($new_data['perms'])) - { - $new_data['user_perms'] = implode(".",$new_data['perms']); - } - - // Handle the Extended Fields. - $this->saveExtended($new_data); - - - - - return $new_data; - } - - - function saveExtended($new_data) - { - $update = array(); - $fieldtype = array(); - foreach($this->extended as $key) // Grab Extended field data. - { - $update['data'][$key] = vartrue($new_data['ue'][$key],'_NULL_'); - } - - e107::getMessage()->addDebug(print_a($update,true)); - - if(!empty($update)) - { - e107::getUserExt()->addFieldTypes($update); - - if(!e107::getDb()->count('user_extended', '(user_extended_id)', "user_extended_id=".intval($new_data['submit_value']))) - { - $update['data']['user_extended_id'] = intval($new_data['submit_value']); - if(e107::getDb()->insert('user_extended', $update)) - { - // e107::getMessage()->addSuccess(LAN_UPDATED.': '.ADLAN_78); // not needed see pull/1816 - e107::getMessage()->addDebug(LAN_UPDATED.': '.ADLAN_78); // let's put it in debug instead - } - else - { - e107::getMessage()->addError(LAN_UPDATED_FAILED.': '.ADLAN_78); - $error = e107::getDb()->getLastErrorText(); - e107::getMessage()->addDebug($error); - e107::getMessage()->addDebug(print_a($update,true)); - - - e107::getDb()->getLastErrorText(); - } - } - else - { - $update['WHERE'] = 'user_extended_id='. intval($new_data['submit_value']); - - if(e107::getDb()->update('user_extended',$update)===false) - { - e107::getMessage()->addError(LAN_UPDATED_FAILED.': '.ADLAN_78); - $error = e107::getDb()->getLastErrorText(); - e107::getMessage()->addDebug($error); - e107::getMessage()->addDebug(print_a($update,true)); - - } - else - { - e107::getMessage()->reset(E_MESSAGE_SUCCESS)->addSuccess(LAN_UPDATED); - e107::getMessage()->addDebug(LAN_UPDATED.': '.ADLAN_78); // let's put it in debug instead - } - } - } - - - } - - - /** - * Unban user trigger - * @param int $userid - * @return void - */ - public function ListUnbanTrigger($userid) - { - $sql = e107::getDb(); - $tp = e107::getParser(); - $sysuser = e107::getSystemUser($userid, false); - - if(!$sysuser->getId()) - { - e107::getMessage()->addError(USRLAN_223); - return; - } - - $row = e107::user($userid); - - $sql->update("user", "user_ban='0' WHERE user_id='".$userid."' "); - $sql->delete("banlist"," banlist_ip='{$row['user_ip']}' "); - - $vars = array('x'=>$sysuser->getId(), 'y'=> $sysuser->getName(), 'z'=> $sysuser->getValue('email')); - - e107::getAdminLog()->log_event('USET_06', $tp->lanVars( USRLAN_162, $vars), E_LOG_INFORMATIVE); - e107::getMessage()->addSuccess("(".$sysuser->getId().".".$sysuser->getName()." - ".$sysuser->getValue('email').") ".USRLAN_9); - - // List data reload - $this->getTreeModel()->load(true); - } - - /** - * Ban user trigger - * @param int $userid - * @return void - */ - public function ListBanTrigger($userid) - { - $sql = e107::getDb(); - $mes = e107::getMessage(); - $admin_log = e107::getAdminLog(); - $iph = e107::getIPHandler(); - $tp = e107::getParser(); - - $sysuser = e107::getSystemUser($userid, false); - if(!$sysuser->getId()) - { - $mes->addError(USRLAN_223); - return; - } - $row = $sysuser->getData(); - - if (($row['user_perms'] == "0") || ($row['user_perms'] == "0.")) - { - $mes->addWarning(USRLAN_7); - } - else - { - if ($sql->update("user","user_ban='1' WHERE user_id='".$userid."' ")) - { - $vars = array('x'=>$row['user_id'], 'y'=> $row['user_name']); - e107::getLog()->add('USET_05',$tp->lanVars(USRLAN_161, $vars), E_LOG_INFORMATIVE); - $mes->addSuccess("(".$userid.".".$row['user_name']." - {$row['user_email']}) ".USRLAN_8); - } - if (trim($row['user_ip']) == "") - { - $mes->addInfo(USRLAN_135); - } - else - { - if($sql->count('user', '(*)', "user_ip = '{$row['user_ip']}' AND user_ban=0 AND user_id <> {$userid}") > 0) - { - // Other unbanned users have same IP address - $mes->addWarning(str_replace("{IP}", $iph->ipDecode($row['user_ip']), USRLAN_136)); - } - else - { - if ($iph->add_ban(6, USRLAN_149.$row['user_name'].'/'.$row['user_loginname'], $row['user_ip'], USERID)) - { - // Successful IP ban - $mes->addSuccess(str_replace("{IP}", $iph->ipDecode($row['user_ip']), USRLAN_137)); - } - else - { - // IP address on whitelist - $mes->addWarning(str_replace("{IP}", $iph->ipDecode($row['user_ip']), USRLAN_150)); - } - } - } - } - - // List data reload - $this->getTreeModel()->load(true); - } - - /** - * Activate user trigger - */ - public function ListVerifyTrigger($userid) - { - $e_event = e107::getEvent(); - $admin_log = e107::getAdminLog(); - $sysuser = e107::getSystemUser($userid, false); - $userMethods = e107::getUserSession(); - $mes = e107::getMessage(); - $tp = e107::getParser(); - - $uid = intval($userid); - if ($sysuser->getId()) - { - $sysuser->set('user_ban', '0') - ->set('user_sess', ''); - - $row = $sysuser->getData(); - - if ($initUserclasses = $userMethods->userClassUpdate($row, 'userall')) - { - $row['user_class'] = $initUserclasses; - } - - $userMethods->addNonDefaulted($row); - $sysuser->setData($row); - - // $res = $sysuser->getData(); - // e107::getDebug()->log($res); - - $sysuser->save(); - - $vars = array( - 'x' => $sysuser->getId(), - 'y' => $sysuser->getName(), - 'z' => $sysuser->getValue('email') - ); - - e107::getLog()->add('USET_10', $tp->lanVars( USRLAN_166, $vars), E_LOG_INFORMATIVE); - e107::getEvent()->trigger('userfull', $row); //BC - e107::getEvent()->trigger('admin_user_activated', $row); - - $mes->addSuccess(USRLAN_86." (#".$sysuser->getId()." : ".$sysuser->getName().' - '.$sysuser->getValue('email').")"); - - $this->getTreeModel()->load(true); - - if ((int) e107::pref('core', 'user_reg_veri') == 2) - { - $message = USRLAN_114." ".$row['user_name'].",\n\n".USRLAN_122." ".SITENAME.".\n\n".USRLAN_123."\n\n"; - $message .= str_replace("{SITEURL}", SITEURL, USRLAN_139); - - $options = array( - 'mail_subject' => USRLAN_113.' '.SITENAME, - 'mail_body' => nl2br($message), - ); - - // $options['debug'] = 1; - - if($ret =$sysuser->email('email', $options)) - { - $mes->addSuccess(USRLAN_224." ".$sysuser->getName().' ('.$sysuser->getValue('email').')'); - } - else - { - $mes->addError(USRLAN_225." ".$sysuser->getName().' ('.$sysuser->getValue('email').')'); - } - } - } - else - { - $mes->addError(USRLAN_223); - return; - } - } - - /** - * Main admin login as system user trigger - */ - public function ListLoginasTrigger($userid) - { - $mes = e107::getMessage(); - - if(e107::getUser()->getSessionDataAs()) - { - $mes->addWarning(USRLAN_AS_3); - } - elseif(e107::getUser()->loginAs($userid)) - { - $sysuser = e107::getSystemUser($userid); - $user = e107::getUser(); - - // TODO - lan - $mes->addSuccess('Successfully logged in as '.$sysuser->getName().' [logout]') - ->addSuccess('Please, Leave Admin to browse the system as this user. Use "Logout" option in Administration to end front-end session'); - - $search = array('--UID--', '--NAME--', '--EMAIL--', '--ADMIN_UID--', '--ADMIN_NAME--', '--ADMIN_EMAIL--'); - $replace = array($sysuser->getId(), $sysuser->getName(), $sysuser->getValue('email'), $user->getId(), $user->getName(), $user->getValue('email')); - - // TODO - lan - $lan = 'Administrator --ADMIN_EMAIL-- (#--ADMIN_UID--, --ADMIN_NAME--) has logged in as the user --EMAIL-- (#--UID--, --NAME--)'; - - e107::getLog()->log_event('USET_100', str_replace($search, $replace, $lan), E_LOG_INFORMATIVE); - - $eventData = array('user_id' => $sysuser->getId(), 'admin_id' => $user->getId()); - e107::getEvent()->trigger('loginas', $eventData); // BC - e107::getEvent()->trigger('admin_user_loginas', $eventData); - - } - } - - /** - * Main admin logout as a system user trigger - */ - public function LogoutasObserver() - { - $user = e107::getUser(); - $sysuser = e107::getSystemUser($user->getSessionDataAs(), false); - - if(e107::getUser()->logoutAs() && $sysuser && $sysuser->getId()) - { - // TODO - lan - e107::getMessage()->addSuccess('Successfully logged out from '.$sysuser->getName().' ('.$sysuser->getValue('email').') account', 'default', true); - - $search = array('--UID--', '--NAME--', '--EMAIL--', '--ADMIN_UID--', '--ADMIN_NAME--', '--ADMIN_EMAIL--'); - $replace = array($sysuser->getId(), $sysuser->getName(), $sysuser->getValue('email'), $user->getId(), $user->getName(), $user->getValue('email')); - - // TODO - lan - $lan = 'Administrator --ADMIN_EMAIL-- (#--ADMIN_UID--, --ADMIN_NAME--) has logged out as the user --EMAIL-- (#--UID--, --NAME--)'; - - e107::getAdminLog()->log_event('USET_101', str_replace($search, $replace, $lan), E_LOG_INFORMATIVE); - - $eventData = array('user_id' => $sysuser->getId(), 'admin_id' => $user->getId()); - e107::getEvent()->trigger('logoutas', $eventData); //BC - e107::getEvent()->trigger('admin_user_logoutas', $eventData); - $this->redirect('list', 'main', true); - } - - - if(!$sysuser->getId()) e107::getMessage()->addError(LAN_USER_NOT_FOUND); - } - - public function LogoutasPage() - { - // System Message only on non-successful logout as another user - } - - /** - * Remove admin status trigger - */ - public function ListUnadminTrigger($userid) - { - $user = e107::getUser(); - $sysuser = e107::getSystemUser($userid, false); - $mes = e107::getMessage(); - $tp = e107::getParser(); - - if(!$user->checkAdminPerms('3')) - { - $mes->addError(USRLAN_226, 'default', true); - - //$search = array('--UID--', '--NAME--', '--EMAIL--', '--ADMIN_UID--', '--ADMIN_NAME--', '--ADMIN_EMAIL--'); - $vars = array( - 'u' => $sysuser->getId(), - 'v' => $sysuser->getName(), - 'w' => $sysuser->getValue('email'), - 'x' => $user->getId(), - 'y' => $user->getName(), - 'z' => $user->getValue('email') - ); - - e107::getAdminLog()->log_event('USET_08', $tp->lanVars(USRLAN_244,$vars), E_LOG_INFORMATIVE); - $this->redirect('list', 'main', true); - } - - if ($sysuser->isMainAdmin()) - { - $mes->addError(USRLAN_5); - } - else - { - if($sysuser->set('user_admin', '0')->set('user_perms', '')->save()) - { - $vars = array('x'=>$sysuser->getId(), 'y'=>$sysuser->getName(), 'z'=>$sysuser->getValue('email')); - - e107::getAdminLog()->log_event('USET_09',$tp->lanVars(USRLAN_165, $vars), E_LOG_INFORMATIVE); - $mes->addSuccess($sysuser->getName()." (".$sysuser->getValue('email').") ".USRLAN_6); - $this->getTreeModel()->load(true); - } - else - { - $mes->addError(USRLAN_227); - } - } - } - - /** - * Admin manage observer - * @return void - */ - public function AdminObserver() - { - if($this->getPosted('go_back')) - { - $this->redirect('list', 'main', true); - } - - $userid = $this->getId(); - $sql = e107::getDb(); - $user = e107::getUser(); - $sysuser = e107::getSystemUser($userid, false); - $admin_log = e107::getAdminLog(); - $mes = e107::getMessage(); - $tp = e107::getParser(); - - if(!$user->checkAdminPerms('3')) - { - $mes->addError(USRLAN_226, 'default', true); - // $search = array('--UID--', '--NAME--', '--EMAIL--', '--ADMIN_UID--', '--ADMIN_NAME--', '--ADMIN_EMAIL--'); - - $vars = array( - 'u' => $sysuser->getId(), - 'v' => $sysuser->getName(), - 'w' => $sysuser->getValue('email'), - 'x' => $user->getId(), - 'y' => $user->getName(), - 'z' => $user->getValue('email') - ); - - // $replace = array($sysuser->getId(), $sysuser->getName(), $sysuser->getValue('email'), $user->getId(), $user->getName(), $user->getValue('email')); - - e107::getLog()->add('USET_08', $tp->lanVars( USRLAN_245,$vars), E_LOG_INFORMATIVE); - - $this->redirect('list', 'main', true); - } - - if(!$sysuser->getId()) - { - $mes->addError(USRLAN_223, 'default', true); - $this->redirect('list', 'main', true); - } - - - if($this->getPosted('update_admin')) - { - e107::getUserPerms()->updatePerms($userid, $_POST['perms']); - $this->redirect('list', 'main', true); - } - - if(!$sysuser->isAdmin()) // Security Check Only. Admin status check is added during 'updatePerms'. - { - // $sysuser->set('user_admin', 1)->save(); //"user","user_admin='1' WHERE user_id={$userid}" - // $lan = str_replace(array('--UID--', '--NAME--', '--EMAIL--'), array($sysuser->getId(), $sysuser->getName(), $sysuser->getValue('email')), USRLAN_164); - // e107::getLog()->add('USET_08', $lan, E_LOG_INFORMATIVE); - // $mes->addSuccess($lan); - $rplc_from = array('[x]', '[y]', '[z]'); - $rplc_to = array($sysuser->getId(), $sysuser->getName(), $sysuser->getValue('email')); - $message = str_replace($rplc_from, $rplc_to, USRLAN_228); - $message = e107::getParser()->toHTML($message,true); - $mes->addWarning($message); - $mes->addWarning(e107::getParser()->toHTML(USRLAN_229,true)); - } - - } - - /** - * Admin manage page - */ - public function AdminPage() - { - $request = $this->getRequest(); - $response = $this->getResponse(); - $sysuser = e107::getSystemUser($request->getId(), false); - //$sysuser->load($request->getId(), true); - $prm = e107::getUserPerms(); - $frm = e107::getForm(); - - $response->appendBody($frm->open('adminperms')) - ->appendBody($prm->renderPermTable('grouped', $sysuser->getValue('perms'))) - ->appendBody($prm->renderCheckAllButtons()) - ->appendBody($prm->renderSubmitButtons().$frm->token()) - ->appendBody($frm->close()); - - $this->addTitle(str_replace(array('[x]', '[y]'), array($sysuser->getName(), $sysuser->getValue('email')), USRLAN_230)); - } - - protected function checkAllowed($class_id) // check userclass change is permitted. - { - $e_userclass = e107::getUserClass(); - if (!isset ($e_userclass->class_tree[$class_id])) - { - return false; - } - if (!getperms("0") && !check_class($e_userclass->class_tree[$class_id]['userclass_editclass'])) - { - return false; - } - return true; - } - - protected function manageUserclass($userid, $uclass, $mode = false) - { - $request = $this->getRequest(); - $response = $this->getResponse(); - $sysuser = e107::getSystemUser($userid, false); - - $admin_log = e107::getAdminLog(); - $e_userclass = e107::getUserClass(); - $sql = e107::getDb(); - - $remuser = true; - $mes = e107::getMessage(); - - if(!$sysuser->getId()) - { - $mes->addError(USRLAN_223); - return false; - } - - $curClass = array(); - if($mode !== 'update') - { - $curClass = $sysuser->getValue('class') ? explode(',', $sysuser->getValue('class')) : array(); - } - - foreach ($uclass as $a) - { - $a = intval($a); - if(!$this->checkAllowed($a)) - { - $mes->addError(USRLAN_231); - return false; - } - - if($a != 0) // if 0 - then do not add. - { - $curClass[] = $a; - } - } - - if($mode == "remove") // remove selected classes - { - $curClass = array_diff($curClass, $uclass); - } - elseif($mode == "clear") // clear all classes - { - $curClass = array(); - } - - $curClass = array_unique($curClass); - - $svar = is_array($curClass) ? implode(",", $curClass) : ""; - $check = $sysuser->set('user_class', $svar)->save(); - - if($check) - { - $message = UCSLAN_9; - if ($this->getPosted('notifyuser')) - { - $options = array(); - $message .= "
".UCSLAN_1.": ".$sysuser->getName()."
"; - - $messaccess = ''; - foreach ($curClass as $a) - { - if (!isset ($e_userclass->fixed_classes[$a])) - { - $messaccess .= $e_userclass->class_tree[$a]['userclass_name']." - ".$e_userclass->class_tree[$a]['userclass_description']."\n"; - } - } - if ($messaccess == '') $messaccess = UCSLAN_12."\n"; - - $message = USRLAN_256." ".$sysuser->getName().",\n\n".UCSLAN_4." ".SITENAME."\n( ".SITEURL." )\n\n".UCSLAN_5.": \n\n".$messaccess."\n".UCSLAN_10."\n".SITEADMIN; - // $admin_log->e_log_event(4,__FILE__."|".__FUNCTION__."@".__LINE__,"DBG","User class change",str_replace("\n","
",$message),FALSE,LOG_TO_ROLLING); - - $options['mail_subject'] = UCSLAN_2; - $options['mail_body'] = nl2br($message); - - $sysuser->email('email', $options); - //sendemail($send_to,$subject,$message); - } - e107::getLog()->add('USET_14', str_replace(array('[x]','[y]'), array($userid, $svar), UCSLAN_11), E_LOG_INFORMATIVE); - - $mes->addSuccess(nl2br($message)); - } - else - { - // $mes->add("Update Failed", E_MESSAGE_ERROR); - if($check === false) - { - $sysuser->setMessages(); // move messages to the default stack - } - else - { - $mes->addInfo(LAN_NO_CHANGE); - } - } - } - - /** - * Update user class trigger - */ - public function UserclassUpdateclassTrigger() - { - $this->manageUserclass($this->getId(), $this->getPosted('userclass'), 'update'); - } - - /** - * Back to user list trigger (userclass page) - */ - public function UserclassBackTrigger() - { - $this->redirect('list', 'main', true); - } - - /** - * Manage userclasses page - */ - public function UserclassPage() - { - $request = $this->getRequest(); - $response = $this->getResponse(); - $sysuser = e107::getSystemUser($request->getId(), false); - $e_userclass = e107::getUserClass(); - $userid = $this->getId(); - $frm = e107::getForm(); - - $caption = UCSLAN_6." ".$sysuser->getName().' - '.$sysuser->getValue('email')." (".$sysuser->getClassList(true).")"; - $this->addTitle($caption); - - $text = "
-
-
- - - - - - - - - - - -
"; - $text .= $e_userclass->vetted_tree('userclass', array($e_userclass,'checkbox_desc'), $sysuser->getValue('class'), 'classes, no-excludes'); - $text .= ' -
- '; - - $text .= "
- ".$frm->hidden('userid', $userid)." - ".$frm->checkbox_label(USRLAN_255.'  ', 'notifyuser', 1)." - ".$frm->admin_button('etrigger_updateclass', LAN_NO_RECORDS_FOUND, 'update')." - ".$frm->admin_button('etrigger_back', LAN_BACK, 'cancel')." -
-
-
-
"; - - $response->appendBody($text); - } - - /** - * Resend user activation email trigger - */ - public function ListResendTrigger($userid) - { - $this->resendActivation($userid); - } - - /** - * Resend user activation email helper - * FIXME - better Subject/Content for the activation email when user is bounced/deactivated. - */ - protected function resendActivation($id, $lfile = '') - { - - $sysuser = e107::getSystemUser($id, false); - $key = $sysuser->getValue('sess'); - $mes = e107::getMessage(); - - if(!$sysuser->getId()) - { - $mes->addError(USRLAN_223); - return false; - } - - if(!$key || !$sysuser->getValue('ban')) - { - $mes->addError(USRLAN_232); - $mes->addDebug("key: ".$key." ban: ".$sysuser->getValue('ban')); - return false; - } - - // Check for a Language field, and if present, send the email in the user's language. - // FIXME - make all system emails to be created from HTML email templates, this should fix the multi-lingual issue when sending multiple emails - if ($lfile == "") - { - $lan = $sysuser->getValue('language'); - if ($lan) - { - $lfile = e_LANGUAGEDIR.$lan.'/lan_signup.php'; - } - } - if ($lfile && is_readable($lfile)) - { - require_once($lfile); - } - else - { - //@FIXME use email templates by Language - require_once (e_LANGUAGEDIR.e_LANGUAGE."/lan_signup.php"); - } - if(!$lan) $lan = e_LANGUAGE; - - // FIXME switch to e107::getUrl()->create(), use email content templates - //$return_address = (substr(SITEURL,- 1) == "/") ? SITEURL."signup.php?activate.".$sysuser->getId().".".$key : SITEURL."/signup.php?activate.".$sysuser->getId().".".$key; - $return_address = SITEURL."signup.php?activate.".$sysuser->getId().".".$key; - // $message = LAN_EMAIL_01." ".$sysuser->getName()."\n\n".LAN_SIGNUP_24." ".SITENAME.".\n".LAN_SIGNUP_21."\n\n"; - // $message .= "".$return_address.""; - - - $userInfo = array( - 'user_id' => $sysuser->getId(), - 'user_name' => $sysuser->getName(), - 'user_email' => $sysuser->getValue('email'), - 'user_sess' => $key, - 'user_loginname' => $sysuser->getValue('loginname'), - ); - - - $passwordInput = e107::getPref('signup_option_password', 2); - - if(empty($passwordInput)) // auto-generated password at signup. - { - $newPwd = e107::getUserSession()->resetPassword($userInfo['user_id']); - } - else - { - $newPwd = '**********'; - } - - $message = 'null'; - - $check = $sysuser->email('signup', array( - 'mail_subject' => LAN_SIGNUP_98, - 'mail_body' => nl2br($message), - 'user_password' => $newPwd - ), $userInfo); - - if ($check) - { - $vars = array('x'=> $sysuser->getId(), 'y'=>$sysuser->getName(), 'z'=> $sysuser->getValue('email')); - $message = e107::getParser()->lanVars(USRLAN_167,$vars); - e107::getLog()->add('USET_11', $message, E_LOG_INFORMATIVE); - $mes->addSuccess(USRLAN_140.": ".$sysuser->getName()." (".$sysuser->getValue('email').") ({$lan}) "); - } - else - { - $mes->addError(USRLAN_141.": ".$sysuser->getName().' ('.$sysuser->getValue('email').')'); - } - return $check; - } - - /** - * Test user email observer - */ - public function TestObserver() - { - $sysuser = e107::getSystemUser($this->getId(), false); - $mes = e107::getMessage(); - $email = $sysuser->getValue('email'); - - if(!$sysuser->getId()) - { - $mes->addError(USRLAN_223, 'default', true); - $this->redirect('list', 'main', true); - } - - $result = $this->testEmail($email); - if($result) - { - $this->setParam('testSucces', $result); - $mes->addSuccess($email.' - '.USRLAN_233); - } - else - { - $mes->addError($email.' - '.USRLAN_234, 'default', true); // Invalid. - $this->redirect('list', 'main', true); - } - - } - - public function TestCancelTrigger() - { - $this->redirect('list', 'main', true); - } - - /** - * Resend activation email page - only if tested email is valid - */ - public function TestPage() - { - $response = $this->getResponse(); - $sysuser = e107::getSystemUser($this->getId(), false); - $userid = $this->getId(); - $email = $sysuser->getValue('email'); - $frm = e107::getForm(); - - $caption = str_replace('[x]', $email, USRLAN_119); - $this->addTitle($caption); - - $text = "".LAN_BACK.""; - $text .= '
'.htmlspecialchars($this->getParam('testSucces')).'
'; - $text .= "
-
-
-
- ".$frm->hidden('useraction', 'resend')." - ".$frm->hidden('userid', $userid)." - ".$frm->hidden('userip', $sysuser->getValue('ip'))." - ".$frm->admin_button('resend', USRLAN_112, 'update')." -
-
-
-
"; - - $response->appendBody($text); - } - - /** - * Test user email helper - */ - protected function testEmail($email) - { - list($adminuser,$adminhost) = explode('@',SITEADMINEMAIL, 2); - - $validator = new email_validation_class; - $validator->localuser = $adminuser; - $validator->localhost = $adminhost; - $validator->timeout = 5; - $validator->debug = 1; - $validator->html_debug = 0; - - ob_start(); - $email_status = $validator->ValidateEmailBox($email); - $text = ob_get_contents(); - ob_end_clean(); - - if ($email_status == 1) - { - return $text; - } - - return false; - } - - /** - * Set user status to require verification - available for bounced users - */ - public function ListReqverifyTrigger($userid) - { - $sysuser = e107::getSystemUser($userid, false); - - if(!$sysuser->getId()) - { - e107::getMessage()->addError(USRLAN_223, 'default', true); - return; - } - - $sysuser->set('user_ban', 2) - ->set('user_sess', e_user_model::randomKey()); - - if($sysuser->save()) - { - e107::getMessage()->addSuccess(USRLAN_235); - - // TODO - auto-send email or not - discuss - $this->resendActivation($userid); - - //FIXME admin log - - // Reload tree - $this->getTreeModel()->load(true); - return; - } - - e107::getMessage()->addError(USRLAN_236); - } - - public function EditSubmitTrigger() - { - $this->_manageSubmit('beforeUpdate', 'afterUpdate', 'onUpdateError', 'edit', true); // force update. - } - - - - /** - * Quick Add user submit trigger - */ - public function AddSubmitTrigger() - { - $e107cache = e107::getCache(); - $userMethods = e107::getUserSession(); - $mes = e107::getMessage(); - $sql = e107::getDb(); - $e_event = e107::getEvent(); - $admin_log = e107::getAdminLog(); - $pref = e107::getPref(); - - if (!$_POST['ac'] == md5(ADMINPWCHANGE)) - { - exit; - } - - $e107cache->clear('online_menu_member_total'); - $e107cache->clear('online_menu_member_newest'); - $error = false; - - if (isset ($_POST['generateloginname'])) - { - $_POST['loginname'] = $userMethods->generateUserLogin($pref['predefinedLoginName']); - } - - $_POST['password2'] = $_POST['password1'] = $_POST['password']; - - // Now validate everything - $allData = validatorClass::validateFields($_POST, $userMethods->userVettingInfo, true); - - // Fix Display and user name - if (!check_class($pref['displayname_class'], $allData['data']['user_class'])) - { - if ($allData['data']['user_name'] != $allData['data']['user_loginname']) - { - $allData['data']['user_name'] = $allData['data']['user_loginname']; - $message = str_replace('[x]', $allData['data']['user_loginname'], USRLAN_237); - $message = e107::getParser()->toHTML($message,true); - $mes->addWarning($message); - //$allData['errors']['user_name'] = ERR_FIELDS_DIFFERENT; - } - } - - // Do basic validation - validatorClass::checkMandatory('user_name, user_loginname', $allData); - - // Check for missing fields (email done in userValidation() ) - validatorClass::dbValidateArray($allData, $userMethods->userVettingInfo, 'user', 0); - - // Do basic DB-related checks - $userMethods->userValidation($allData); - - // Do user-specific DB checks - if (!isset($allData['errors']['user_password'])) - { - // No errors in password - keep it outside the main data array - $savePassword = $allData['data']['user_password']; - // Delete the password value in the output array - unset ($allData['data']['user_password']); - } - - // Restrict the scope of this - unset($_POST['password2'], $_POST['password1']); - - if (count($allData['errors'])) - { - $temp = validatorClass::makeErrorList($allData, 'USER_ERR_','%n - %x - %t: %v', '
', $userMethods->userVettingInfo); - $mes->addError($temp); - $error = true; - } - - // Always save some of the entered data - then we can redisplay on error - $user_data = & $allData['data']; - - if($error) - { - $this->setParam('user_data', $user_data); - return; - } - - if(varset($_POST['perms'])) - { - $allData['data']['user_admin'] = 1; - $allData['data']['user_perms'] = implode('.',$_POST['perms']); - } - - - - $user_data['user_password'] = $userMethods->HashPassword($savePassword, $user_data['user_loginname']); - $user_data['user_join'] = time(); - - e107::getMessage()->addDebug("Password Hash: ".$user_data['user_password']); - - if ($userMethods->needEmailPassword()) - { - // Save separate password encryption for use with email address - $user_prefs = e107::getArrayStorage()->unserialize($user_data['user_prefs']); - $user_prefs['email_password'] = $userMethods->HashPassword($savePassword, $user_data['user_email']); - $user_data['user_prefs'] = e107::getArrayStorage()->serialize($user_prefs); - unset($user_prefs); - } - - $userMethods->userClassUpdate($allData['data'], 'userall'); - - //FIXME - (SecretR) there is a better way to fix this (missing default value, sql error in strict mode - user_realm is to be deleted from DB later) - $allData['data']['user_realm'] = ''; - - // Set any initial classes - $userMethods->addNonDefaulted($user_data); - validatorClass::addFieldTypes($userMethods->userVettingInfo, $allData); - - $userid = $sql->insert('user', $allData); - if ($userid) - { - $this->saveExtended(array('submit_value'=>$userid)); - - $sysuser = e107::getSystemUser(false, false); - $sysuser->setData($allData['data']); - $sysuser->setId($userid); - $user_data['user_id'] = $userid; - - // Add to admin log - e107::getLog()->add('USET_02',"UName: {$user_data['user_name']}; Email: {$user_data['user_email']}", E_LOG_INFORMATIVE); - - // Add to user audit trail - e107::getLog()->user_audit(USER_AUDIT_ADD_ADMIN, $user_data, 0, $user_data['user_loginname']); - e107::getEvent()->trigger('userfull', $user_data); - e107::getEvent()->trigger('admin_user_created', $user_data); - - // send everything available for user data - bit sparse compared with user-generated signup - if(isset($_POST['sendconfemail'])) - { - $check = false; - - // Send confirmation email to user - switch ((int) $_POST['sendconfemail']) - { - case 0: - // activate, don't notify - $check = -1; - break; - - case 1: - // activate and send password - $check = $sysuser->email('quickadd', array( - 'user_password' => $savePassword, - 'mail_subject' => USRLAN_187, - 'activation_url' => USRLAN_246, - )); - break; - - case 2: - // require activation and send password and activation link - $sysuser->set('user_ban', 2) - ->set('user_sess', e_user_model::randomKey()) - ->save(); - - $check = $sysuser->email('quickadd', array( - 'user_password' => $savePassword, - 'mail_subject' => USRLAN_187, - 'activation_url' => SITEURL."signup.php?activate.".$sysuser->getId().".".$sysuser->getValue('sess'), - )); - break; - } - - if($check && $check !== -1) - { - $mes->addSuccess(USRLAN_188); - } - elseif(!$check) - { - $mes->addError(USRLAN_189); - } - } - - // $message = str_replace('--NAME--', htmlspecialchars($user_data['user_name'], ENT_QUOTES, CHARSET), USRLAN_174); - $message = USRLAN_172; // "User account has been created with the following:" ie. keep it simple so it can easily be copied and pasted. - - // Always show Login name and password - //if (isset($_POST['generateloginname'])) - { - $mes->addSuccess($message) - ->addSuccess(USRLAN_128.': '.htmlspecialchars($user_data['user_loginname'], ENT_QUOTES, CHARSET).''); - } - - //if (isset($_POST['generatepassword'])) - { - $mes->addSuccess(LAN_PASSWORD.': '.htmlspecialchars($savePassword, ENT_QUOTES, CHARSET).''); - } - return; - } - else - { - $mes->addError(LAN_CREATED_FAILED); - $mes->addError($sql->getLastErrorText()); - } - } - - /** - * Quick add user page - */ - function AddPage() - { - $prm = e107::getUserPerms(); - //$list = $prm->getPermList(); - $frm = e107::getForm(); - $e_userclass = e107::getUserClass(); - $pref = e107::getPref(); - $user_data = $this->getParam('user_data'); - - // $this->addTitle(LAN_USER_QUICKADD); - - $text = "
".$frm->open("core-user-adduser-form",null,null,'autocomplete=0')." -
-
- - - - - - - - - - - - - - - - - - - - - - - - "; - - - - $text .= " - - - - - - - - - "; - - if (!isset ($user_data['user_class'])) $user_data['user_class'] = varset($pref['initial_user_classes']); - $temp = $e_userclass->vetted_tree('class', array($e_userclass, 'checkbox_desc'), $user_data['user_class'], 'classes, no-excludes'); - - if ($temp) - { - $text .= " - - - \n"; - } - - // Make Admin. - $text .= " - - - - - "; - - - $text .= " - -
".USRLAN_61." - ".$frm->text('username', varset($user_data['user_name']), varset($pref['displayname_maxlength'], 15), array('size'=>'xlarge'))." -
".USRLAN_128."
- ".$frm->text('loginname', varset($user_data['user_loginname']), varset($pref['loginname_maxlength'], 30), array('size'=>'xlarge'))."   - ".$frm->checkbox_label(USRLAN_170, 'generateloginname', 1, varset($pref['predefinedLoginName'], false))." -
".USRLAN_129." - ".$frm->text('realname', varset($user_data['user_login']), 30, array('size'=>'xlarge'))." -
".LAN_PASSWORD."".$frm->password('password', '', 128, array('size' => 'xlarge', 'class' => 'tbox e-password', 'generate' => 1, 'strength' => 1, 'autocomplete' => 'new-password'))." -
".USRLAN_64." - ".$frm->text('email', varset($user_data['user_email']), 100, array('size'=>'xlarge'))." -
".USRLAN_239." - ".$frm->select('sendconfemail', array('0' => USRLAN_240, '1' => USRLAN_241, '2' => USRLAN_242), (int) varset($_POST['sendconfemail'], 0), array('size'=>'xlarge'))." -
".USRLAN_181."
-
- ".USRLAN_120." - - ".USRLAN_120." -
- {$temp} -
-
".USRLAN_35." - ".USRLAN_243." -
- "; - - $text .= $prm->renderPermTable('grouped'); - - $text .= " -
-
-
- ".$frm->admin_trigger('submit', USRLAN_60, 'create')." - ".$frm->token()." - -
-
- -
- "; - - - return $text; - //$ns->tablerender(USRLAN_59,$mes->render().$text); - } - - public function RanksUpdateTrigger() - { - $fg = array(); - $ranks_calc = ''; - $ranks_flist = ''; - $config = e107::getConfig(); - foreach ($_POST['op'] as $f => $o) - { - $cfg[$f]['op'] = $o; - $cfg[$f]['val'] = varset($_POST['val'][$f],''); - if ($_POST['val'][$f]) - { - $ranks_calc .= ($ranks_calc ? ' + ' : '').'({'.$f.'} '." $o {$_POST['val'][$f]}".' )'; - $ranks_flist .= ($ranks_flist ? ',' : '').$f; - } - } - - //Delete existing rank config - e107::getDb()->delete('generic', "gen_type = 'user_rank_config'"); - - $tmp = array(); - $tmp['data']['gen_type'] = 'user_rank_config'; - $tmp['data']['gen_chardata'] = serialize($cfg); - $tmp['_FIELD_TYPES']['gen_type'] = 'string'; - $tmp['_FIELD_TYPES']['gen_chardata'] = 'escape'; - - //Add the new rank config - e107::getDb()->insert('generic', $tmp); - - // save prefs - $config->set('ranks_calc', $ranks_calc); - $config->set('ranks_flist', $ranks_flist); - $config->save(); - $config->resetMessages(); - - //Delete existing rank data - e107::getDb()->delete('generic',"gen_type = 'user_rank_data'"); - - //Add main site admin info - $tmp = array(); - $tmp['_FIELD_TYPES']['gen_datestamp'] = 'int'; - $tmp['_FIELD_TYPES']['gen_ip'] = 'todb'; - $tmp['_FIELD_TYPES']['gen_user_id'] = 'int'; - $tmp['_FIELD_TYPES']['gen_chardata'] = 'todb'; - $tmp['_FIELD_TYPES']['gen_intdata'] = 'int'; - $tmp['data']['gen_datestamp'] = 1; - $tmp['data']['gen_type'] = 'user_rank_data'; - $tmp['data']['gen_ip'] = $_POST['calc_name']['main_admin']; - $tmp['data']['gen_user_id'] = varset($_POST['calc_pfx']['main_admin'],0); - $tmp['data']['gen_chardata'] = $_POST['calc_img']['main_admin']; - e107::getDb()->insert('generic',$tmp); - - //Add site admin info - unset ($tmp['data']); - $tmp['data']['gen_type'] = 'user_rank_data'; - $tmp['data']['gen_datestamp'] = 2; - $tmp['data']['gen_ip'] = $_POST['calc_name']['admin']; - $tmp['data']['gen_user_id'] = varset($_POST['calc_pfx']['admin'],0); - $tmp['data']['gen_chardata'] = $_POST['calc_img']['admin']; - e107::getDb()->insert('generic', $tmp); - - //Add all current site defined ranks - if (isset ($_POST['field_id'])) - { - foreach ($_POST['field_id'] as $fid => $x) - { - unset ($tmp['data']); - $tmp['data']['gen_type'] = 'user_rank_data'; - $tmp['data']['gen_ip'] = varset($_POST['calc_name'][$fid],''); - $tmp['data']['gen_user_id'] = varset($_POST['calc_pfx'][$fid],0); - $tmp['data']['gen_chardata'] = varset($_POST['calc_img'][$fid],''); - $tmp['data']['gen_intdata'] = varset($_POST['calc_lower'][$fid],'_NULL_'); - e107::getDb()->insert('generic', $tmp); - } - } - - //Add new rank, if posted - if (varset($_POST['new_calc_lower'])) - { - unset ($tmp['data']); - $tmp['data']['gen_type'] = 'user_rank_data'; - $tmp['data']['gen_datestamp'] = 0; - $tmp['data']['gen_ip'] = varset($_POST['new_calc_name']); - $tmp['data']['gen_user_id'] = varset($_POST['new_calc_pfx'],0); - $tmp['data']['gen_chardata'] = varset($_POST['new_calc_img']); - $tmp['data']['gen_intdata'] = varset($_POST['new_calc_lower']); - e107::getDb()->insert('generic', $tmp); - } - - e107::getMessage()->addSuccess(LAN_UPDATED); //XXX maybe not needed see pull/1816 - e107::getCache()->clear_sys('nomd5_user_ranks'); - } - - function RanksDeleteTrigger($posted) - { - $rankId = (int) key($posted); - - e107::getCache()->clear_sys('nomd5_user_ranks'); - if (e107::getDb()->delete('generic',"gen_id='{$rankId}'")) - { - e107::getMessage()->addSuccess(LAN_DELETED); - } - else - { - e107::getMessage()->addError(LAN_DELETED_FAILED); - } - } - - function RanksPage() - { - $frm = e107::getForm(); - $e107 = e107::getInstance(); - $pref = e107::getPref(); - $mes = e107::getMessage(); - /** @var users_admin_form_ui $ui */ - $ui = $this->getUI(); - $tp = e107::getParser(); - - $ranks = e107::getRank()->getRankData(); - $tmp = e107::getFile()->get_files(e_IMAGE.'ranks', '.*?\.(png|gif|jpg)'); - - // $this->addTitle(LAN_USER_RANKS); - - foreach($tmp as $k => $v) - { - $imageList[] = $v['fname']; - } - unset($tmp); - natsort($imageList); - - $text = $frm->open('core-user-ranks-form'); - - - $fields = array( - 'type' => array('title' => USRLAN_207, 'type' => 'text', 'width' => 'auto', 'thclass' => 'left', 'class' => 'left'), - 'rankName' => array('title' => USRLAN_208, 'type' => 'text', 'width' => 'auto', 'thclass' => 'left', 'class' => 'left'), - 'lowThresh' => array('title' => USRLAN_209, 'type' => 'text', 'width' => 'auto', 'thclass' => 'left', 'class' => 'left'), - 'langPrefix' => array('title' => USRLAN_210, 'type' => 'text', 'width' => 'auto', 'thclass' => 'left', 'class' => 'left'), - 'rankImage' => array('title' => USRLAN_211, 'type' => 'text', 'width' => 'auto', 'thclass' => 'left', 'class' => 'left'), - ); - - - $text .= " - ". - $frm->colGroup($fields, array_keys($fields)). - $frm->thead($fields, array_keys($fields)); - - $info = $ranks['special'][1]; - $val = $tp->toForm($info['name']); - $text .= " - - - - - - - - "; - $info = $ranks['special'][2]; - $val = $tp->toForm($info['name']); - $text .= " - - - - - - - - - - - "; - - foreach ($ranks['data'] as $k => $r) - { - $pfx_checked = ($r['lan_pfx'] ? "checked='checked'" : ''); - $text .= " - - - - - - - - "; - } - - $text .= " - - - - - - - - - - - "; - - $text .= '
".LAN_MAINADMIN." - ".$frm->text('calc_name[main_admin]', $val)." - N/A".$frm->checkbox('calc_pfx[main_admin]', 1, $info['lan_pfx'] ? true : false)."".$ui->RankImageDropdown($imageList,'calc_img[main_admin]',$info['image'])."
".LAN_ADMIN." - ".$frm->text('calc_name[admin]', $val)." - N/A".$frm->checkbox('calc_pfx[admin]', 1, $info['lan_pfx'] ? true : false)."".$ui->RankImageDropdown($imageList, 'calc_img[admin]', $info['image'])."
 
".USRLAN_212." - - - ".$frm->number("calc_lower[{$k}]", $r['thresh'])."".$frm->checkbox("calc_pfx[{$k}]", 1, $r['lan_pfx'] ? true : false)."".$ui->RankImageDropdown($imageList, "calc_img[$k]", $r['image'])." ". - $frm->submit_image("etrigger_delete[{$r['id']}]", LAN_DELETE, 'delete', LAN_CONFIRMDEL.": [{$r['name']}]?")." -
 
".USRLAN_214."".$frm->text('new_calc_name', '')."".$frm->number('new_calc_lower', '')."".$frm->checkbox('new_calc_pfx', 1, false)."".$ui->RankImageDropdown($imageList, 'new_calc_img')."
-
- '.$frm->admin_trigger('update', 'no-value', 'update', LAN_UPDATE).' -
- '; - - return $text; - } - - // ================== OLD CODE backup =============> - - // It might be rewritten with user info option (ui trigger) - // Old trigger code - // if ((isset ($_POST['useraction']) && $_POST['useraction'] == "userinfo") || $_GET['userinfo']) - // { - // $ip = ($_POST['userip']) ? $_POST['userip'] : $_GET['userinfo']; - // $user->user_info($ip); - // } - function user_info($ipd) - { - global $ns, $sql, $e107; - - if (isset($ipd)) - { - $bullet = ''; - if(defined('BULLET')) - { - $bullet = ''; - } - elseif(file_exists(THEME.'images/bullet2.gif')) - { - $bullet = ''; - } - // TODO - move to e_userinfo.php - $obj = new convert; - $sql->db_Select("chatbox", "*", "cb_ip='$ipd' LIMIT 0,20"); - $host = $e107->get_host_name($ipd); - $text = USFLAN_3." ".$ipd." [ ".USFLAN_4.": $host ]
- ".USFLAN_5." - -

"; - while (list($cb_id, $cb_nick, $cb_message, $cb_datestamp, $cb_blocked, $cb_ip ) = $sql->fetch()) - { - $datestamp = $obj->convert_date($cb_datestamp, "short"); - $post_author_id = substr($cb_nick, 0, strpos($cb_nick, ".")); - $post_author_name = substr($cb_nick, (strpos($cb_nick, ".")+1)); - $text .= $bullet." - ".$post_author_name." (".USFLAN_6.": ".$post_author_id.") -
- ".$datestamp." -
- ". $cb_message." -
-
"; - } - - $text .= "
"; - - $sql->db_Select("comments", "*", "comment_ip='$ipd' LIMIT 0,20"); - while (list($comment_id, $comment_item_id, $comment_author, $comment_author_email, $comment_datestamp, $comment_comment, $comment_blocked, $comment_ip) = $sql->fetch()) - { - $datestamp = $obj->convert_date($comment_datestamp, "short"); - $post_author_id = substr($comment_author, 0, strpos($comment_author, ".")); - $post_author_name = substr($comment_author, (strpos($comment_author, ".")+1)); - $text .= $bullet." - ".$post_author_name." (".USFLAN_6.": ".$post_author_id.") -
- ".$datestamp." -
". $comment_comment." -
-
"; - } - - } - - $ns->tablerender(USFLAN_7, $text); - } - - - - - function maintenancePage() - { - $frm = e107::getForm(); - $ns = e107::getRender(); - $sql = e107::getDb(); - $tp = e107::getParser(); - - $age = array( - 1=> LAN_UI_1_HOUR, 3=> LAN_UI_3_HOURS, 6=> LAN_UI_6_HOURS, 12=> LAN_UI_12_HOURS, 24 => LAN_UI_24_HOURS, 48 => LAN_UI_48_HOURS, 72 => LAN_UI_3_DAYS); - - $count = $sql->count('user','(*)',"user_ban = 2 "); - $caption = $tp->lanVars(USRLAN_252,$count); - - $text = $frm->open('userMaintenance','post'); - - $text .= " - - - - - - -
".$caption." - -
".USRLAN_253." ".$frm->select('resendAge', $age, 24).$frm->checkbox('resetPasswords',1,false,USRLAN_254). - "
".$frm->userclass('resendClass',false, null )."". - $frm->button('resendToAll', 1, 'warning', LAN_GO)." - - -
"; - - $text .= $frm->close(); - - return $text; - - - - - } - - - /** - * Send an activation email to all unactivated users older than so many hours. - * @param bool $resetPasswords - * @param int $age in hours. ie. older than 24 hours will be sent an email. - */ - function resend_to_all($resetPasswords=false, $age=24, $class='') - { - global $sql,$pref; - $tp = e107::getParser(); - $sql = e107::getDb(); - $sql2 = e107::getDb('toall'); - - $emailLogin = e107::getPref('allowEmailLogin'); - - e107::lan('core','signup'); - - $ageOpt = intval($age)." hours ago"; - $age = strtotime($ageOpt); - - // $query = "SELECT u.*, ue.* FROM `#user` AS u LEFT JOIN `#user_extended` AS ue ON ue.user_extended_id = u.user_id WHERE u.user_ban = 2 AND u.user_email != '' AND u.user_join < ".$age." ORDER BY u.user_id DESC"; - - - $query = "SELECT u.* FROM `#user` AS u WHERE u.user_ban = 2 AND u.user_email != '' AND u.user_join < ".$age." "; - - if(!empty($class)) - { - $query .= " AND FIND_IN_SET( ".intval($class).", u.user_class) "; - } - - $query .= " ORDER BY u.user_id DESC"; - - $sql->gen($query); - - $recipients = array(); - - $usr = e107::getUserSession(); - - while ($row = $sql->fetch()) - { - - if($resetPasswords === true) - { - $rawPassword = $usr->generateRandomString('********'); - $sessKey = e_user_model::randomKey(); - - $updateQry = array( - 'user_sess' => $sessKey, - 'user_password' => $usr->HashPassword($rawPassword, $row['user_loginname']), - 'WHERE' => 'user_id = '.$row['user_id']." LIMIT 1" - ); - - if(!$sql2->update('user',$updateQry)) - { - - e107::getMessage()->addError("Error updating user's password. #".$row['user_id']." : ".$row['user_email']); - e107::getMessage()->addDebug(print_a($updateQry,true)); - - // break; - } - else - { - e107::getMessage()->addInfo("Updated ".$row['user_id']." : ".$row['user_email']); - } - - - $row['user_sess'] = $sessKey; - - } - else - { - $rawPassword = '(*** hidden ***)'; - } - - $activationUrl = SITEURL."signup.php?activate.".$row['user_id'].".".$row['user_sess']; - - - - $recipients[] = array( - 'mail_recipient_id' => $row['user_id'], - 'mail_recipient_name' => $row['user_name'], // Should this use realname? - 'mail_recipient_email' => $row['user_email'], - 'mail_target_info' => array( - 'USERID' => $row['user_id'], - 'LOGINNAME' => (intval($emailLogin) === 1) ? $row['user_email'] : $row['user_loginname'], - 'PASSWORD' => $rawPassword, - 'DISPLAYNAME' => $tp->toDB($row['user_name']), - 'SUBJECT' => LAN_SIGNUP_98, - 'USERNAME' => $row['user_name'], - 'USERLASTVISIT' => $row['user_lastvisit'], - 'ACTIVATION_LINK' => ''.$activationUrl.'', // Warning: switching the quotes on this will break the template. - 'ACTIVATION_URL' => $activationUrl, - 'DATE_SHORT' => $tp->toDate(time(),'short'), - 'DATE_LONG' => $tp->toDate(time(),'long'), - 'SITEURL' => SITEURL - ) - ); - - // echo $row['user_id']." ".$row['user_sess']." ".$row['user_name']." ".$row['user_email']."
"; - - } - - $siteadminemail = e107::getPref('siteadminemail'); - $siteadmin = e107::getPref('siteadmin'); - - $mailer = e107::getBulkEmail(); - - // Create the mail body - $mailData = array( - 'mail_total_count' => count($recipients), - 'mail_content_status' => MAIL_STATUS_TEMP, - 'mail_create_app' => 'core', - 'mail_title' => 'RESEND ACTIVATION', - 'mail_subject' => LAN_SIGNUP_98, - 'mail_sender_email' => e107::getPref('replyto_email',$siteadminemail), - 'mail_sender_name' => e107::getPref('replyto_name',$siteadmin), - 'mail_notify_complete' => 0, // NEVER notify when this email sent!!!!! - 'mail_body' => 'null', - 'template' => 'signup', - 'mail_send_style' => 'signup' - ); - - - $mailer->sendEmails('signup', $mailData, $recipients, array('mail_force_queue'=>1)); - $totalMails = count($recipients); - - $url = e_ADMIN."mailout.php?mode=pending&action=list"; - - e107::getMessage()->addSuccess("Total emails added to mail queue: ".$totalMails); - - } - - // --------------------------------------------------------------------- - // Bounce handling - FIXME convert to cron job - // --------------------------------------------------------------------- - // $bounce_act has the task to perform: - // 'first_check' - initial read of list of bounces - // 'delnonbounce' - delete any emails that aren't bounces - // 'clearemailbounce' - delete email address for any user whose emails bounced - // 'delchecked' - delete the emails whose comma-separated IDs are in $bounce_arr - // 'delall' - delete all bounced emails - - /* - function check_bounces($bounce_act = 'first_check',$bounce_arr = '') - { - ### old Trigger code for bounce check - // $bounce_act = ''; - // if (isset ($_POST['check_bounces'])) - // $bounce_act = 'first_check'; - // if (isset ($_POST['delnonbouncesubmit'])) - // $bounce_act = 'delnonbounce'; - // if (isset ($_POST['clearemailbouncesubmit'])) - // $bounce_act = 'clearemailbounce'; - // if (isset ($_POST['delcheckedsubmit'])) - // $bounce_act = 'delchecked'; - // if (isset ($_POST['delallsubmit'])) - // $bounce_act = 'delall'; - // if ($bounce_act) - // { - // $user->check_bounces($bounce_act,implode(',',$_POST['delete_email'])); - // require_once ("footer.php"); - // exit; - // } - - global $sql,$pref; - include (e_HANDLER.'pop3_class.php'); - if (!trim($bounce_act)) - { - $bounce_act = 'first_check'; - } - // echo "Check bounces. Action: {$bounce_act}; Entries: {$bounce_arr}
"; - $obj = new receiveMail($pref['mail_bounce_user'],$pref['mail_bounce_pass'],$pref['mail_bounce_email'],$pref['mail_bounce_pop3'],varset($pref['mail_bounce_type'],'pop3')); - $del_count = 0; - if ($bounce_act != 'first_check') - { - // Must do some deleting - $obj->connect(); - $tot = $obj->getTotalMails(); - $del_array = explode(',',$bounce_arr); - for ($i = 1; $i <= $tot; $i++) - { - // Scan all emails; delete current one if meets the criteria - $dodel = false; - switch ($bounce_act) - { - case 'delnonbounce' : - $head = $obj->getHeaders($i); - $dodel = (!$head['bounce']); - break; - case 'clearemailbounce' : - if (!in_array($i,$del_array)) - break; - $head = $obj->getHeaders($i); - if ($head['bounce']) - { - if (preg_match("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i",$obj->getBody($i),$result)) - { - $usr_email = trim($result[0]); - } - if ($sql->db_Select('user','user_id, user_name, user_email',"user_email='".$usr_email."' ")) - { - $row = $sql->fetch(); - if ($sql->db_Update('user',"`user_email`='' WHERE `user_id` = '".$row['user_id']."' ") !== false) - { - // echo "Deleting user email {$row['user_email']} for user {$row['user_name']}, id={$row['user_id']}
"; - $dodel = true; - } - } - } - break; - case 'delall' : - $dodel = true; - break; - case 'delchecked' : - $dodel = in_array($i,$del_array); - break; - } - if ($dodel) - { - // echo "Delete email ID {$i}
"; - $obj->deleteMails($i); - $del_count++; - // Keep track of number of emails deleted - } - } - // End - Delete one email - $obj->close_mailbox(); - // This actually deletes the emails - } - // End of email deletion - // Now list the emails that are left - $obj->connect(); - $tot = $obj->getTotalMails(); - $found = false; - $DEL = ($pref['mail_bounce_delete']) ? true : false; - $text = "
- \n"; - - $identifier = deftrue('MAIL_IDENTIFIER', 'X-e107-id'); - - for ($i = 1; $i <= $tot; $i++) - { - $head = $obj->getHeaders($i); - if ($head['bounce']) - { - // Its a 'bounce' email - if (preg_match('/.*'.$identifier.':(.*)MIME/',$obj->getBody($i),$result)) - { - if ($result[1]) - { - $id[$i] = intval($result[1]); - // This should be a user ID - but not on special mailers! - // Try and pull out an email address from body - should be the one that failed - if (preg_match("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i",$obj->getBody($i),$result)) - { - $emails[$i] = "'".$result[0]."'"; - } - $found = true; - } - } - elseif (preg_match("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i",$obj->getBody($i),$result)) - { - if ($result[0] && $result[0] != $pref['mail_bounce_email']) - { - $emails[$i] = "'".$result[0]."'"; - $found = true; - } - elseif ($result[1] && $result[1] != $pref['mail_bounce_email']) - { - $emails[$i] = "'".$result[1]."'"; - $found = true; - } - } - if ($DEL && $found) - { - // Auto-delete bounced emails once noticed (if option set) - $obj->deleteMails($i); - $del_count++; - } - } - else - { - // Its a warning message or similar - // $id[$i] = ''; // Don't worry about an ID for now - // Try and pull out an email address from body - should be the one that failed - if (preg_match("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i",$obj->getBody($i),$result)) - { - $wmails[$i] = "'".$result[0]."'"; - } - } - $text .= "\n"; - } - if ($del_count) - { - e107::getLog()->add('USET_13', e107::getParser()->lanVars(USRLAN_169, $del_count),E_LOG_INFORMATIVE); - } - if ($tot) - { - // Option to delete emails - only if there are some in the list - $text .= "
#e107-idemailSubjectBounce
".$i."".$id[$i]."".(isset ($emails[$i]) ? $emails[$i] : $wmails[$i])."".$head['subject']."".($head['bounce'] ? ADMIN_TRUE_ICON : ADMIN_FALSE_ICON); - $text .= "
- \n - \n - \n - \n - "; - } - $text .= "
"; - array_unique($id); - array_unique($emails); - $all_ids = implode(',',$id); - $all_emails = implode(',',$emails); - $obj->close_mailbox(); - // This will actually delete emails - // $tot has total number of emails in the mailbox - $found = count($emails); - // $found - Number of bounce emails found - // $del_count has number of emails deleted - // Update bounce status for users - $ed = $sql->db_Update('user',"user_ban=3 WHERE (`user_id` IN (".$all_ids.") OR `user_email` IN (".$all_emails.")) AND user_sess !='' "); - if (!$ed) - $ed = '0'; - $this->show_message(str_replace(array('[w]','[x]','[y]','[z]'),array($tot,$del_count,$ed,$found),USRLAN_155).$text); - } - */ -// ------- FIXME Prune Users move to cron -------------- -// if (isset ($_POST['prune'])) -// { - // $e107cache->clear('online_menu_member_total'); - // $e107cache->clear('online_menu_member_newest'); - // $text = USRLAN_56.' '; - // $bantype = $_POST['prune_type']; - // if ($bantype == 30) - // // older than 30 days. - // { - // $bantype = 2; - // $ins = " AND user_join < ".strtotime("-30 days"); - // } - // if ($sql->db_Select("user","user_id, user_name","user_ban= {$bantype}".$ins)) - // { - // $uList = $sql->db_getList(); - // foreach ($uList as $u) - // { - // $text .= $u['user_name']." "; - // $sql->db_Delete("user","user_id='{$u['user_id']}' "); - // $sql->db_Delete("user_extended","user_extended_id='{$u['user_id']}' "); - // } - // e107::getLog()->add('USET_04',str_replace(array('[x]','--TYPE--'),array(count($uList),$bantype),USRLAN_160),E_LOG_INFORMATIVE); - // } - // $ns->tablerender(USRLAN_57,"
".$text."
"); - // unset ($text); -// } -} - - -class users_admin_form_ui extends e_admin_form_ui -{ - - - function user_admin($curval,$mode, $att) - { - $att['type'] = 'boolean'; - -// $uid = $this->getController()->getModel()->get('user_id'); - $perms = $this->getController()->getModel()->get('user_perms'); - - if($mode == 'filter' && getperms('3')) - { - return array(0=>LAN_NO, '1'=>LAN_YES); - } - - if($mode == 'read' || (str_replace(".","",$perms) == '0') || !getperms('3')) - { - return $this->renderValue('user_admin',$curval,$att); - } - - if($mode == 'write') - { - return $this->renderElement('user_admin',$curval,$att); - } - - - - } - - - function user_extended($curval,$mode, $att) - { - if($mode == 'read') - { - $field = $att['field']; - - if($this->getController()->getAction() == 'list') - { - $data = $this->getController()->getListModel()->get($field); // ($att['field']); - } - else - { - $data = $this->getController()->getModel()->get($field); // ($att['field']); - } - - - - return e107::getUserExt()->renderValue($data, $att['ueType']); - - - } - if($mode == 'write') - { - // e107::getUserExt()->user_extended_edit - // return 'hello'; - $field = $att['field']; - /** @var users_admin_ui $controller */ - $controller = $this->getController(); - $extData = $controller->getExtended(); - $extData[$field]['user_extended_struct_required'] = 0; - - return e107::getUserExt()->user_extended_edit($extData[$field],$curval); - - // return print_a($att,true); - } - - - } - - - - - - function user_perms($curval,$mode) - { - $perms = $this->getController()->getModel()->get('user_perms'); - $uid = $this->getController()->getModel()->get('user_id'); - - if($mode == 'read' || (str_replace(".","",$perms) == '0' && $uid == USERID) || !getperms('3')) - { - return e107::getUserPerms()->renderPerms($curval,$uid); - } - if($mode == 'write') - { - $prm = e107::getUserPerms(); - $text = "".USRLAN_221.""; - $text .= "'; - return $text; - } - - - } - - function user_password($curval,$mode) - { - if($mode == 'read') - { - if(empty($curval)) - { - return "No password!"; - } - - // if(getperms('0')) - { - - $type = e107::getUserSession()->getHashType($curval, 'array'); - $num = $type[0]; - - $styles= array(0=>'label-danger',1=>'label-warning', 3=>'label-success'); - - return "".$type[1].""; - } - } - if($mode == 'write') - { - $fieldName = 'user_password_'. $this->getController()->getId(); - - return $this->password($fieldName, '', 128, array('size' => 50, 'class' => 'tbox e-password', 'placeholder' => USRLAN_251, 'generate' => 1, 'strength' => 1, 'required'=>0, 'autocomplete'=>'new-password')); - } - - - } - - - - - - - function user_ban($curval,$mode) - { - $bo = array( - ''.LAN_ACTIVE.'', - "".LAN_BANNED."", - "".LAN_NOTVERIFIED."", - "".LAN_BOUNCED."", - "".USRLAN_56."", // Deleted - ); - - if($mode == 'filter' || $mode == 'batch') - { - return $bo; - } - - $perms = $this->getController()->getModel()->get('user_perms'); - - if($mode == 'write') - { - - if(str_replace(".","",$perms) == '0') - { - return "
".vartrue($bo[$curval],' ')."
"; - } - - return $this->select('user_ban',$bo,$curval); - } - - return vartrue($bo[$curval],' '); // ($curval == 1) ? ADMIN_TRUE_ICON : ''; - } - - - /* - function user_class($curval,$mode) - { - - $e_userclass = new user_class; - $frm = e107::getForm(); - $list = $e_userclass->uc_required_class_list("classes"); - if($mode == 'filter') - { - return $list; - } - - if($mode == 'write') //FIXME userclasses are NOT be saved since they are an array. - { - return $frm->select('user_class', $list, $curval, 'description=1&multiple=1'); - // return $frm->uc_select('user_class[]', $curval, 'admin,classes', 'description=1&multiple=1');// doesn't work correctly. - } - - - //FIXME TODO - option to append userclass to existing value. - if($mode == 'batch') - { - //$list['#delete'] = "(clear userclass)"; // special - return $list; - } - $tmp = explode(",",$curval); - $text = array(); - foreach($tmp as $v) - { - $text[] = $list[$v]; - } - return implode("
",$text); // $list[$curval]; - - }*/ - - - /* - function user_status($curval,$mode) - { - - $row = $this->getController()->getListModel()->getData(); - - $text = ""; - if ($row['user_perms'] == "0") - { - $text .= "
".LAN_MAINADMIN."
"; - } - else - if ($row['user_admin']) - { - $text .= ""; - } - else - if ($row['user_ban'] == 1) - { - $text .= ""; - } - else - if ($row['user_ban'] == 2) - { - $text .= "
".LAN_NOTVERIFIED."
"; - } - else - if ($row['user_ban'] == 3) - { - $text .= "
".LAN_BOUNCED."
"; - } - else - { - $text .= " "; - } - - return $text; - - - } - */ - - //TODO Reduce to simple edit/delete buttons only Other options included on edit page or available via inline or batch editing. - function options($val, $mode) // old drop-down options. - { - $controller = $this->getController(); - - if($controller->getMode() != 'main' || $controller->getAction() != 'list') return; - $row = $controller->getListModel()->getData(); - - if(!getperms('4')) - { - // return; - } - - - // extract($row); - - $user_id = intval($row['user_id']); - $user_ip = $row['user_ip']; - $user_admin = $row['user_admin']; - - $head = "
- - - - - "; - - // "; - // $foot = "
"; - - $btn = '
- - -
'; - - if(!empty($opts)) - { - return $head.$btn; - } - else - { - return ''; - } - - // return ($text) ? $head.$text.$foot . $btn : ""; - } - - - function RankImageDropdown(&$imgList, $field, $curVal = '') - { - $ret = " - '; - return $ret; - } - - -} - - - class users_ranks_ui extends e_admin_ui - { - protected $pluginTitle = ADLAN_36; - protected $pluginName = 'user_ranks'; - protected $table = 'generic'; - protected $pid = 'gen_id'; - protected $perPage = 15; - protected $listQry = "SELECT * FROM `#generic` WHERE gen_type='user_rank_data' "; - protected $listOrder = " CASE gen_datestamp WHEN 1 THEN 1 WHEN 2 THEN 2 WHEN 3 THEN 3 WHEN 0 THEN 4 END, gen_intdata "; - - protected $fields = array ( - 'checkboxes' => array ( 'title' => '', 'type' => null, 'data' => null, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect', ), - 'gen_id' => array ( 'title' => LAN_ID, 'nolist'=>true, 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'gen_type' => array ( 'title' => LAN_BAN, 'type' => 'hidden', 'data' => 'str', 'width' => 'auto', 'batch' => true, 'filter' => true, 'inline' => true, 'help' => '', 'readParms' => '', 'writeParms' => 'value=user_rank_data', 'class' => 'left', 'thclass' => 'left', ), - 'gen_ip' => array ( 'title' => USRLAN_208, 'type' => 'text', 'data' => 'str', 'inline'=>true, 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'gen_intdata' => array ( 'title' => USRLAN_209, 'type' => 'text', 'batch'=>false, 'data' => 'int', 'inline'=>true, 'width' => 'auto', 'help' => '', 'readParms' => 'default=-', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), - - 'gen_datestamp' => array ( 'title' => 'Special', 'type' => 'hidden', 'nolist'=>true, 'data' => 'int', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'gen_user_id' => array ( 'title' => USRLAN_210, 'type' => 'boolean', 'batch'=>true, 'data' => 'int', 'inline'=>true, 'width' => '15%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), - //'gen_chardata' => array ( 'title' => LAN_ICON, 'type' => 'dropdown', 'data' => 'str', 'inline'=>true, 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => array(), 'class' => 'left', 'thclass' => 'left', ), - 'gen_chardata' => array ( 'title' => LAN_ICON, 'type' => 'method', 'data' => 'str', 'inline'=>true, 'width' => 'auto', 'help' => '', 'readParms' => array(), 'writeParms' => array(), 'class' => 'left', 'thclass' => 'left', ), - - - 'options' => array ( 'title' => LAN_OPTIONS, 'type' =>'method', 'data' => null, 'width' => '10%', 'thclass' => 'center last', 'class' => 'right last', 'forced' => '1', 'readParms'=>'edit=0' ), - ); - - protected $fieldpref = array('gen_datestamp', 'gen_type', 'gen_ip', 'gen_intdata', 'gen_user_id', 'gen_chardata'); - - - // optional - public function init() - { - $tmp = e107::getFile()->get_files(e_IMAGE.'ranks', '.*?\.(png|gif|jpg)'); - - $mode = $this->getMode(); - $action = $this->getAction(); - - $existing = e107::getDb()->gen("SELECT gen_id FROM #generic WHERE gen_type='user_rank_data' LIMIT 1 "); - - if($mode == 'ranks' && ($action == 'list') && !$existing) - { - $this->createDefaultRecords(); - } - - // $this->addTitle(LAN_USER_RANKS); - - foreach($tmp as $k => $v) - { - $id = $v['fname']; - $this->fields['gen_chardata']['writeParms']['optArray'][$id] = $v['fname']; - } - - unset($tmp); - // natsort($imageList); - } - - public function afterDelete($data, $id, $deleted_check) - { - e107::getCache()->clear_sys('nomd5_user_ranks'); - } - - public function afterUpdate($new_data, $old_data, $id) - { - e107::getCache()->clear_sys('nomd5_user_ranks'); - } - - private function createDefaultRecords() - { - - $tmp = array(); - $tmp['_FIELD_TYPES']['gen_datestamp'] = 'int'; - $tmp['_FIELD_TYPES']['gen_ip'] = 'todb'; - $tmp['_FIELD_TYPES']['gen_user_id'] = 'int'; - $tmp['_FIELD_TYPES']['gen_chardata'] = 'todb'; - $tmp['_FIELD_TYPES']['gen_intdata'] = 'int'; - - - //Add main site admin info - $tmp['data']['gen_datestamp'] = 1; - $tmp['data']['gen_type'] = 'user_rank_data'; - $tmp['data']['gen_ip'] = LAN_MAINADMIN; - $tmp['data']['gen_user_id'] = 1; - $tmp['data']['gen_chardata'] = 'English_main_admin.png'; - $tmp['data']['gen_intdata'] = 0; - e107::getDb()->insert('generic',$tmp); - unset ($tmp['data']); - - - //Add site admin info - $tmp['data']['gen_type'] = 'user_rank_data'; - $tmp['data']['gen_datestamp'] = 2; - $tmp['data']['gen_ip'] = LAN_ADMIN; - $tmp['data']['gen_user_id'] = 1; - $tmp['data']['gen_chardata'] = 'English_admin.png'; - $tmp['data']['gen_intdata'] = 0; - - - e107::getDb()->insert('generic', $tmp); - - for($i=1; $i < 11; $i++) - { - unset ($tmp['data']); - $tmp['data']['gen_type'] = 'user_rank_data'; - $tmp['data']['gen_datestamp'] = 0; - $tmp['data']['gen_ip'] = "Level ".$i; - $tmp['data']['gen_user_id'] = 0; - $tmp['data']['gen_chardata'] = "lev".$i.".png"; - $tmp['data']['gen_intdata'] = ($i * 150); - - e107::getDb()->insert('generic', $tmp); - } - - - - } - - } - - - - class users_ranks_ui_form extends e_admin_form_ui - { - // Override the default Options field. - function options($parms, $value, $id, $attributes) - { - - if($attributes['mode'] == 'read') - { - parse_str(str_replace('&', '&', e_QUERY), $query); - $query['action'] = 'edit'; - $query['id'] = $id; - $query = http_build_query($query, null, '&'); - - $text = " - ".ADMIN_EDIT_ICON.""; - - $special = $this->getController()->getListModel()->get('gen_datestamp'); - - if($special == 0) - { - $text .= $this->submit_image('menu_delete['.$id.']', $id, 'delete', LAN_DELETE.' [ ID: '.$id.' ]', array('class' => 'action delete btn btn-default')); - } - - return $text; - } - } - - function gen_chardata($curVal, $mode, $parms=null) - { - switch($mode) - { - case 'read': - return '
'.$curVal; - break; - - case 'write': - $opts = $this->getController()->getFields()['gen_chardata']['writeParms']['optArray']; - return e107::getForm()->select('gen_chardata', $opts, $curVal); - - case 'filter': - case 'batch': - return null; - break; - - } - } - - - } - - - -new users_admin(); -require_once ('auth.php'); - -e107::getAdminUI()->runPage(); - -require_once ("footer.php"); + array( + 'controller' => 'users_admin_ui', + 'path' => null, + 'ui' => 'users_admin_form_ui', + 'uipath' => null, + //'perm' => '0', + ), + 'ranks' => array( + 'controller' => 'users_ranks_ui', + 'path' => null, + 'ui' => 'users_ranks_ui_form', + 'uipath' => null, + //'perm' => '0', + ) + ); + + + protected $adminMenu = array( + 'main/list' => array('caption'=> LAN_MANAGE, 'perm' => '0|4'), + 'main/add' => array('caption'=> LAN_USER_QUICKADD, 'perm' => '4|U0|U1'), + 'main/prefs' => array('caption'=> LAN_OPTIONS, 'perm' => '4|U2'), + 'ranks/list' => array('caption'=> LAN_USER_RANKS, 'perm' => '4|U3'), + 'main/maintenance' => array('caption'=> LAN_MAINTENANCE, 'perm' => '4') + // 'ranks/list' => array('caption'=> LAN_USER_RANKS, 'perm' => '4|U3') + ); + + /* + FIXME - move user prune to Schedule tasks (cron) + $var ['prune']['text'] = LAN_USER_PRUNE; + $var ['prune']['link'] = e_ADMIN.'users.php?action=prune';// Will be moved to "Schedule tasks" + $var ['prune']['perm'] = '4'; + +*/ + protected $adminMenuAliases = array( + 'main/edit' => 'main/list', + 'main/admin' => 'main/list', + 'main/userclass'=> 'main/list', + 'main/test' => 'main/list', + ); + + protected $menuTitle = ADLAN_36; // 'Users' + + protected $adminMenuIcon = 'e-users-24'; + + + function init() + { + + $JS = <<'); // + + $(document).on('click', ".user-action", function(e){ + // e.stopPropagation(); + + var action = $(this).attr('data-action-type'); + var user = $(this).attr('data-action-user'); + + // $('#user-action-indicator-'+user).html(''); // + + $('.user-action-hidden').val(''); // clear all, incase of back-button or auto-fill. + $('#user-action-'+ user).val(action); + $('#core-user-list-form').submit(); + + + }); +JS; + + e107::js('footer-inline', $JS); + e107::css('inline', ' + .user-action { cursor: pointer } + .btn-user-action { margin-right:15px} + + '); + + } + + /** + * Run observers/headers override + * + * @return users_admin + */ + public function runObservers($run_header = true) + { + // Catch useraction + if (isset($_POST['useraction'])) + { + if(is_array($_POST['useraction'])) + { + foreach ($_POST['useraction'] as $key => $val) + { + if ($val) + { + $_POST['useraction'] = $val; + $_POST['userip'] = $_POST['userip'][$key]; + $_POST['userid'] = (int) $key; + break; + } + } + } + + // FIXME IMPORTANT - permissions per action/trigger + + // map useraction to UI trigger + switch ($_POST['useraction']) + { + ### etrigger_delete + case 'deluser': + if($_POST['userid']) + { + $id = (int) $_POST['userid']; + $_POST['etrigger_delete'] = array($id => $id); + $user = e107::getDb()->retrieve('user', 'user_email, user_name', 'user_id='.$id); + $rplc_from = array('[x]', '[y]', '[z]'); + $rplc_to = array($user['user_name'], $user['user_email'], $id); + $message = str_replace($rplc_from, $rplc_to, USRLAN_222); + $this->getController()->deleteConfirmMessage = $message; + } + break; + + // map to List{USERACTION}Trigger() + case 'unban': + case 'ban': + case 'verify': + case 'reqverify': + case 'resend': + case 'loginas': + case 'unadmin': + $_POST['etrigger_'.$_POST['useraction']] = intval($_POST['userid']); + break; + + + case 'logoutas': + $this->getRequest() + ->setQuery(array()) + ->setMode('main') + ->setAction('logoutas'); + break; + + // redirect to AdminObserver/AdminPage() + case 'admin': + case 'adminperms': + $this->getRequest() + ->setQuery(array()) + ->setMode('main') + ->setAction('admin') + ->setId($_POST['userid']); + + $this->getController()->redirect(); + break; + + // redirect to UserclassObserver/UserclassPage() + case 'userclass': + $this->getRequest() + ->setQuery(array()) + ->setMode('main') + ->setAction('userclass') + ->setId($_POST['userid']); + + $this->getController()->redirect(); + break; + + // redirect to TestObserver/TestPage + case 'test': + $this->getRequest() + ->setQuery(array()) + ->setMode('main') + ->setAction('test') + ->setId($_POST['userid']); + + $this->getController()->redirect(); + break; + + // redirect to TestObserver/TestPage + case 'usersettings': + $this->getRequest() + ->setQuery(array()) + ->setMode('main') + ->setAction('edit') + ->setId($_POST['userid']); + $this->getController()->redirect(); + + + //XXX Broken to the point of being unusable. //header('location:'.e107::getUrl()->create('user/profile/edit', 'id='.(int) $_POST['userid'], 'full=1&encode=0')); + // exit; + break; + } + + } + + return parent::runObservers($run_header); + } +} + + +class users_admin_ui extends e_admin_ui +{ + + protected $pluginTitle = ADLAN_36; + protected $pluginName = 'core'; + protected $eventName = 'user'; + protected $table = "user"; + +// protected $listQry = "SELECT SQL_CALC_FOUND_ROWS * FROM #users"; // without any Order or Limit. + protected $listQry = "SELECT SQL_CALC_FOUND_ROWS u.*,ue.* from #user AS u LEFT JOIN #user_extended AS ue ON u.user_id = ue.user_extended_id "; // without any Order or Limit. + + protected $editQry = "SELECT u.*,ue.* FROM #user AS u left join #user_extended AS ue ON u.user_id = ue.user_extended_id WHERE user_id = {ID}"; + + protected $pid = "user_id"; + protected $perPage = 10; + protected $batchDelete = true; + protected $listOrder = 'user_id DESC'; + + /** + * Show confirm screen before (batch/single) delete + * @var boolean + */ + public $deleteConfirmScreen = true; + + /** + * @var boolean + */ + protected $batchCopy = false; + + /** + * List (numerical array) of only disallowed for this controller actions + */ + protected $disallow = array('create'); + + protected $tabs = array(LAN_BASIC, LAN_EXTENDED); + + protected $url = array( + 'route'=>'user/profile/view', + 'name' => 'user_name', + 'description' => 'user_name', + 'vars'=> array('user_id' => true, 'user_name' => true) + ); + + //TODO - finish 'user' type, set 'data' to all editable fields, set 'noedit' for all non-editable fields + protected $fields = array( + 'checkboxes' => array('title'=> '', 'type' => null, 'width' =>'5%', 'forced'=> TRUE, 'thclass'=>'center', 'class'=>'center'), + + 'user_id' => array('title' => LAN_ID, 'tab'=>0, 'type' =>'text', 'data'=>'int', 'width' => '5%','forced' => true, 'readParms'=>'link=sef&target=blank'), +// 'user_status' => array('title' => LAN_STATUS, 'type' => 'method', 'alias'=>'user_status', 'width' => 'auto','forced' => true, 'nosort'=>TRUE), + 'user_ban' => array('title' => LAN_STATUS, 'tab'=>0, 'type' => 'method', 'width' => 'auto', 'filter'=>true, 'batch'=>true,'thclass'=>'center', 'class'=>'center'), + + 'user_name' => array('title' => LAN_USER_01, 'tab'=>0, 'type' => 'text', 'inline'=>true, 'data'=>'safestr', 'width' => 'auto','thclass' => 'left first'), // Display name + 'user_loginname' => array('title' => LAN_USER_02, 'tab'=>0, 'type' => 'text', 'data'=>'safestr', 'width' => 'auto'), // User name + 'user_login' => array('title' => LAN_USER_03, 'tab'=>0, 'type' => 'text', 'inline'=>true, 'data'=>'safestr', 'width' => 'auto'), // Real name (no real vetting) + 'user_customtitle' => array('title' => LAN_USER_04, 'tab'=>0, 'type' => 'text', 'inline'=>true, 'data'=>'safestr', 'width' => 'auto'), // No real vetting + 'user_password' => array('title' => LAN_PASSWORD, 'tab'=>0, 'type' => 'method', 'data'=>'safestr', 'width' => 'auto'), //TODO add md5 option to form handler? + 'user_sess' => array('title' => LAN_SESSION, 'tab'=>0, 'noedit'=>true, 'type' => 'text', 'width' => 'auto'), // Photo + 'user_image' => array('title' => LAN_USER_07, 'tab'=>0, 'type' => 'dropdown', 'data'=>'str', 'width' => 'auto'), // Avatar + 'user_email' => array('title' => LAN_EMAIL, 'tab'=>0, 'type' => 'text', 'inline'=>true, 'data'=>'safestr', 'width' => 'auto', 'writeParms'=>array('size'=>'xxlarge')), + 'user_hideemail' => array('title' => LAN_USER_10, 'tab'=>0, 'type' => 'boolean', 'data'=>'int', 'width' => 'auto', 'thclass'=>'center', 'class'=>'center', 'filter'=>true, 'batch'=>true, 'readParms'=>'trueonly=1'), + 'user_xup' => array('title' => 'Xup', 'tab'=>0, 'noedit'=>true, 'type' => 'text', 'data'=>'str', 'width' => 'auto'), + 'user_class' => array('title' => LAN_USER_12, 'tab'=>0, 'type' => 'userclasses' , 'data'=>'safestr', 'inline'=>true, 'writeParms' => 'classlist=classes,new', 'readParms'=>'classlist=classes,new&defaultLabel=--', 'filter'=>true, 'batch'=>true), + 'user_join' => array('title' => LAN_USER_14, 'tab'=>0, 'noedit'=>true, 'type' => 'datestamp', 'width' => 'auto', 'writeParms'=>'readonly=1'), + 'user_lastvisit' => array('title' => LAN_USER_15, 'tab'=>0, 'noedit'=>true, 'type' => 'datestamp', 'width' => 'auto'), + 'user_currentvisit' => array('title' => LAN_USER_16, 'tab'=>0, 'noedit'=>true, 'type' => 'datestamp', 'width' => 'auto'), + 'user_comments' => array('title' => LAN_COMMENTS, 'tab'=>0, 'noedit'=>true, 'type' => 'int', 'width' => 'auto','thclass'=>'right','class'=>'right'), + 'user_lastpost' => array('title' => USRLAN_195, 'tab'=>0, 'noedit'=>true, 'type' => 'datestamp', 'width' => 'auto'), + 'user_ip' => array('title' => LAN_USER_18, 'tab'=>0, 'noedit'=>true, 'type' => 'ip', 'data'=>'str', 'width' => 'auto'), + // 'user_prefs' => array('title' => LAN_USER_20, 'type' => 'text', 'width' => 'auto'), + 'user_visits' => array('title' => LAN_USER_21, 'tab'=>0, 'noedit'=>true, 'type' => 'int', 'width' => 'auto','thclass'=>'right','class'=>'right'), + 'user_admin' => array('title' => LAN_USER_22, 'tab'=>0, 'type' => 'method', 'width' => 'auto', 'thclass'=>'center', 'class'=>'center', 'filter'=>true, 'batch'=>true, 'readParms'=>'trueonly=1'), + 'user_perms' => array('title' => LAN_USER_23, 'tab'=>0, 'type' => 'method', 'data'=>'str', 'width' => 'auto'), + 'user_pwchange' => array('title' => LAN_USER_24, 'tab'=>0, 'noedit'=>true, 'type'=>'datestamp' , 'width' => 'auto'), + + ); + + protected $fieldpref = array('user_ban','user_name','user_loginname','user_login','user_email','user_class','user_admin'); + + protected $prefs = array( + // 'anon_post' => array('title'=>PRFLAN_32, 'type'=>'boolean'), + 'avatar_upload' => array('title' => USRLAN_44, 'type' => 'boolean', 'writeParms' => 'label=yesno', 'data' => 'int',), + 'photo_upload' => array('title' => USRLAN_53, 'type' => 'boolean', 'writeParms' => 'label=yesno', 'data' => 'int',), + 'im_width' => array('title' => USRLAN_47, 'type' => 'number', 'writeParms' => array('maxlength' => 4), 'help' => USRLAN_48, 'data' => 'int', ), + 'im_height' => array('title' => USRLAN_49, 'type' => 'number', 'writeParms' => array('maxlength' => 4), 'help' => USRLAN_50, 'data' => 'int', ), + 'profile_rate' => array('title' => USRLAN_126, 'type' => 'boolean', 'writeParms' => 'label=yesno', 'data' => 'int',), + 'profile_comments' => array('title' => USRLAN_127, 'type' => 'boolean', 'writeParms' => 'label=yesno', 'data' => 'int',), + 'force_userupdate' => array('title' => USRLAN_133, 'type' => 'boolean', 'writeParms' => 'label=yesno', 'help' => USRLAN_134, 'data' => 'int',), + 'del_unv' => array('title' => USRLAN_93, 'type' => 'number', 'writeParms' => array('maxlength' => 5, 'post' => USRLAN_95), 'help' => USRLAN_94, 'data' => 'int',), + 'track_online' => array('title' => USRLAN_130, 'type' => 'boolean', 'writeParms' => 'label=yesno', 'help' => USRLAN_131, 'data' => 'int',), + 'memberlist_access' => array('title' => USRLAN_146, 'type' => 'userclass', 'writeParms' => 'classlist=public,member,guest,admin,main,classes,nobody', 'data' => 'int',), + 'signature_access' => array('title' => USRLAN_194, 'type' => 'userclass', 'writeParms' => 'classlist=member,admin,main,classes,nobody', 'data' => 'int',), + 'user_new_period' => array('title' => USRLAN_190, 'type' => 'number', 'writeParms' => array('maxlength' => 3, 'post' => LANDT_04s), 'help' => USRLAN_191, 'data' => 'int',), + ); + + public $extended = array(); + public $extendedData = array(); + + + + function getExtended() + { + return $this->extendedData; + } + + function init() + { + + $sql = e107::getDb(); + $tp = e107::getParser(); + + + if(!empty($_POST['resendToAll'])) + { + $resetPasswords = !empty($_POST['resetPasswords']); + $age = vartrue($_POST['resendAge'], 24); + $class = vartrue($_POST['resendClass'], false); + $this->resend_to_all($resetPasswords, $age, $class); + } + + + if($this->getAction() == 'edit') + { + $this->fields['user_class']['noedit'] = true; + } + + + + + + + + // Extended fields - FIXME - better field types + + if($rows = $sql->retrieve('user_extended_struct', '*', "user_extended_struct_type > 0 AND user_extended_struct_text != '_system_' ORDER BY user_extended_struct_parent ASC",true)) + { + // TODO FIXME use the handler to build fields and field attributes + // FIXME a way to load 3rd party language files for extended user fields + e107::coreLan('user_extended'); + + $dataMode = ($this->getAction() === 'list') ? 'str' : false; // allow for search of extended fields. + + foreach ($rows as $row) + { + $field = "user_".$row['user_extended_struct_name']; + // $title = ucfirst(str_replace("user_","",$field)); + $label = $tp->toHTML($row['user_extended_struct_text'],false,'defs'); + $this->fields[$field] = array('__tableField'=>'ue.'.$field, 'title' => $label,'width' => 'auto', 'type'=>'method', 'readParms'=>array('ueType'=>$row['user_extended_struct_type']), 'method'=>'user_extended', 'data'=>$dataMode, 'tab'=>1, 'noedit'=>false); + + $this->extended[] = $field; + $this->extendedData[$field] = $row; + } + } + + + if(empty($this->extended)) + { + $this->tabs = false; + } + + + + $this->fields['user_signature']['writeParms']['data'] = e107::getUserClass()->uc_required_class_list("classes"); + + $this->fields['user_signature'] = array('title' => LAN_USER_09, 'type' => 'textarea', 'data'=>'str', 'width' => 'auto', 'writeParms'=>array('size'=>'xxlarge')); + $this->fields['options'] = array('title'=> LAN_OPTIONS." ", 'type' => 'method', 'forced'=>TRUE, 'width' => '10%', 'thclass' => 'right last', 'class' => 'left'); + + + if(!getperms('4|U0')) // Quick Add User Access Only. + { + unset($this->fields['checkboxes']); + unset($this->fields['options']); + } + + $this->fields['user_image']['writeParms'] = $this->getAvatarList(); + + if(!empty($_GET['readonly'])) + { + foreach($this->fields as $key=>$v) + { + if($key == 'options' || $key == 'checkboxes') + { + continue; + } + + $this->fields[$key]['readonly'] = 2; + + } + } + // print_a($this->fields); + if(!empty($_GET['iframe'])) + { + define('e_IFRAME', true); + } + + + + } + + + + protected function getAvatarList() + { + $avs = array(''=>LAN_NONE); + $upload = array(); + $sys = array(); + $uploaded = e107::getFile()->get_files(e_AVATAR_UPLOAD); + foreach($uploaded as $f) + { + $id = '-upload-'.$f['fname']; + $upload[$id] = $f['fname']; + } + $system = e107::getFile()->get_files(e_AVATAR_DEFAULT); + foreach($system as $f) + { + $id = $f['fname']; + $sys[$id] = $f['fname']; + } + + $avs['uploaded'] = $upload; + $avs['system'] = $sys; + + return $avs; + } + + + public function afterDelete($deletedData, $id=null, $deleted_check) + { + if(!empty($id)) + { + $sql = e107::getDb(); + $sql->delete('user_extended',"user_extended_id = ".$id); + + e107::getCache()->clear('online_menu_member_newest'); + e107::getCache()->clear('online_menu_member_total'); + } + + } + + + + + public function beforeUpdate($new_data, $old_data, $id) + { + $tp = e107::getParser(); + + $pwdField = 'user_password_'.$id; + + if(!empty($new_data[$pwdField])) + { + $new_data['user_password'] = $new_data[$pwdField]; + unset($new_data[$pwdField]); + } + + // e107::getMessage()->addInfo(print_a($new_data,true)); + + if(empty($new_data['user_password'])) + { + $new_data['user_password'] = $old_data['user_password']; + } + else + { + + // issues #3126, #3143: Login not working after admin set a new password using the backend + // Backend used user_login instead of user_loginname (used in usersettings) and did't escape the password. + $savePassword = $new_data['user_password']; + $loginname = $new_data['user_loginname'] ? $new_data['user_loginname'] : $old_data['user_loginname']; + $email = (isset($new_data['user_email']) && $new_data['user_email']) ? $new_data['user_email'] : $old_data['user_email']; + $new_data['user_password'] = e107::getDb()->escape(e107::getUserSession()->HashPassword($savePassword, $loginname), false); + + e107::getMessage()->addDebug("Password Hash: ".$new_data['user_password']); + } + + if(!empty($new_data['perms'])) + { + $new_data['user_perms'] = implode(".",$new_data['perms']); + } + + // Handle the Extended Fields. + $this->saveExtended($new_data); + + + + + return $new_data; + } + + + function saveExtended($new_data) + { + $update = array(); + $fieldtype = array(); + foreach($this->extended as $key) // Grab Extended field data. + { + $update['data'][$key] = vartrue($new_data['ue'][$key],'_NULL_'); + } + + e107::getMessage()->addDebug(print_a($update,true)); + + if(!empty($update)) + { + e107::getUserExt()->addFieldTypes($update); + + if(!e107::getDb()->count('user_extended', '(user_extended_id)', "user_extended_id=".intval($new_data['submit_value']))) + { + $update['data']['user_extended_id'] = intval($new_data['submit_value']); + if(e107::getDb()->insert('user_extended', $update)) + { + // e107::getMessage()->addSuccess(LAN_UPDATED.': '.ADLAN_78); // not needed see pull/1816 + e107::getMessage()->addDebug(LAN_UPDATED.': '.ADLAN_78); // let's put it in debug instead + } + else + { + e107::getMessage()->addError(LAN_UPDATED_FAILED.': '.ADLAN_78); + $error = e107::getDb()->getLastErrorText(); + e107::getMessage()->addDebug($error); + e107::getMessage()->addDebug(print_a($update,true)); + + + e107::getDb()->getLastErrorText(); + } + } + else + { + $update['WHERE'] = 'user_extended_id='. intval($new_data['submit_value']); + + if(e107::getDb()->update('user_extended',$update)===false) + { + e107::getMessage()->addError(LAN_UPDATED_FAILED.': '.ADLAN_78); + $error = e107::getDb()->getLastErrorText(); + e107::getMessage()->addDebug($error); + e107::getMessage()->addDebug(print_a($update,true)); + + } + else + { + e107::getMessage()->reset(E_MESSAGE_SUCCESS)->addSuccess(LAN_UPDATED); + e107::getMessage()->addDebug(LAN_UPDATED.': '.ADLAN_78); // let's put it in debug instead + } + } + } + + + } + + + /** + * Unban user trigger + * @param int $userid + * @return void + */ + public function ListUnbanTrigger($userid) + { + $sql = e107::getDb(); + $tp = e107::getParser(); + $sysuser = e107::getSystemUser($userid, false); + + if(!$sysuser->getId()) + { + e107::getMessage()->addError(USRLAN_223); + return; + } + + $row = e107::user($userid); + + $sql->update("user", "user_ban='0' WHERE user_id='".$userid."' "); + $sql->delete("banlist"," banlist_ip='{$row['user_ip']}' "); + + $vars = array('x'=>$sysuser->getId(), 'y'=> $sysuser->getName(), 'z'=> $sysuser->getValue('email')); + + e107::getAdminLog()->log_event('USET_06', $tp->lanVars( USRLAN_162, $vars), E_LOG_INFORMATIVE); + e107::getMessage()->addSuccess("(".$sysuser->getId().".".$sysuser->getName()." - ".$sysuser->getValue('email').") ".USRLAN_9); + + // List data reload + $this->getTreeModel()->load(true); + } + + /** + * Ban user trigger + * @param int $userid + * @return void + */ + public function ListBanTrigger($userid) + { + $sql = e107::getDb(); + $mes = e107::getMessage(); + $admin_log = e107::getAdminLog(); + $iph = e107::getIPHandler(); + $tp = e107::getParser(); + + $sysuser = e107::getSystemUser($userid, false); + if(!$sysuser->getId()) + { + $mes->addError(USRLAN_223); + return; + } + $row = $sysuser->getData(); + + if (($row['user_perms'] == "0") || ($row['user_perms'] == "0.")) + { + $mes->addWarning(USRLAN_7); + } + else + { + if ($sql->update("user","user_ban='1' WHERE user_id='".$userid."' ")) + { + $vars = array('x'=>$row['user_id'], 'y'=> $row['user_name']); + e107::getLog()->add('USET_05',$tp->lanVars(USRLAN_161, $vars), E_LOG_INFORMATIVE); + $mes->addSuccess("(".$userid.".".$row['user_name']." - {$row['user_email']}) ".USRLAN_8); + } + if (trim($row['user_ip']) == "") + { + $mes->addInfo(USRLAN_135); + } + else + { + if($sql->count('user', '(*)', "user_ip = '{$row['user_ip']}' AND user_ban=0 AND user_id <> {$userid}") > 0) + { + // Other unbanned users have same IP address + $mes->addWarning(str_replace("{IP}", $iph->ipDecode($row['user_ip']), USRLAN_136)); + } + else + { + if ($iph->add_ban(6, USRLAN_149.$row['user_name'].'/'.$row['user_loginname'], $row['user_ip'], USERID)) + { + // Successful IP ban + $mes->addSuccess(str_replace("{IP}", $iph->ipDecode($row['user_ip']), USRLAN_137)); + } + else + { + // IP address on whitelist + $mes->addWarning(str_replace("{IP}", $iph->ipDecode($row['user_ip']), USRLAN_150)); + } + } + } + } + + // List data reload + $this->getTreeModel()->load(true); + } + + /** + * Activate user trigger + */ + public function ListVerifyTrigger($userid) + { + $e_event = e107::getEvent(); + $admin_log = e107::getAdminLog(); + $sysuser = e107::getSystemUser($userid, false); + $userMethods = e107::getUserSession(); + $mes = e107::getMessage(); + $tp = e107::getParser(); + + $uid = intval($userid); + if ($sysuser->getId()) + { + $sysuser->set('user_ban', '0') + ->set('user_sess', ''); + + $row = $sysuser->getData(); + + if ($initUserclasses = $userMethods->userClassUpdate($row, 'userall')) + { + $row['user_class'] = $initUserclasses; + } + + $userMethods->addNonDefaulted($row); + $sysuser->setData($row); + + // $res = $sysuser->getData(); + // e107::getDebug()->log($res); + + $sysuser->save(); + + $vars = array( + 'x' => $sysuser->getId(), + 'y' => $sysuser->getName(), + 'z' => $sysuser->getValue('email') + ); + + e107::getLog()->add('USET_10', $tp->lanVars( USRLAN_166, $vars), E_LOG_INFORMATIVE); + e107::getEvent()->trigger('userfull', $row); //BC + e107::getEvent()->trigger('admin_user_activated', $row); + + $mes->addSuccess(USRLAN_86." (#".$sysuser->getId()." : ".$sysuser->getName().' - '.$sysuser->getValue('email').")"); + + $this->getTreeModel()->load(true); + + if ((int) e107::pref('core', 'user_reg_veri') == 2) + { + $message = USRLAN_114." ".$row['user_name'].",\n\n".USRLAN_122." ".SITENAME.".\n\n".USRLAN_123."\n\n"; + $message .= str_replace("{SITEURL}", SITEURL, USRLAN_139); + + $options = array( + 'mail_subject' => USRLAN_113.' '.SITENAME, + 'mail_body' => nl2br($message), + ); + + // $options['debug'] = 1; + + if($ret =$sysuser->email('email', $options)) + { + $mes->addSuccess(USRLAN_224." ".$sysuser->getName().' ('.$sysuser->getValue('email').')'); + } + else + { + $mes->addError(USRLAN_225." ".$sysuser->getName().' ('.$sysuser->getValue('email').')'); + } + } + } + else + { + $mes->addError(USRLAN_223); + return; + } + } + + /** + * Main admin login as system user trigger + */ + public function ListLoginasTrigger($userid) + { + $mes = e107::getMessage(); + + if(e107::getUser()->getSessionDataAs()) + { + $mes->addWarning(USRLAN_AS_3); + } + elseif(e107::getUser()->loginAs($userid)) + { + $sysuser = e107::getSystemUser($userid); + $user = e107::getUser(); + + // TODO - lan + $mes->addSuccess('Successfully logged in as '.$sysuser->getName().' [logout]') + ->addSuccess('Please, Leave Admin to browse the system as this user. Use "Logout" option in Administration to end front-end session'); + + $search = array('--UID--', '--NAME--', '--EMAIL--', '--ADMIN_UID--', '--ADMIN_NAME--', '--ADMIN_EMAIL--'); + $replace = array($sysuser->getId(), $sysuser->getName(), $sysuser->getValue('email'), $user->getId(), $user->getName(), $user->getValue('email')); + + // TODO - lan + $lan = 'Administrator --ADMIN_EMAIL-- (#--ADMIN_UID--, --ADMIN_NAME--) has logged in as the user --EMAIL-- (#--UID--, --NAME--)'; + + e107::getLog()->log_event('USET_100', str_replace($search, $replace, $lan), E_LOG_INFORMATIVE); + + $eventData = array('user_id' => $sysuser->getId(), 'admin_id' => $user->getId()); + e107::getEvent()->trigger('loginas', $eventData); // BC + e107::getEvent()->trigger('admin_user_loginas', $eventData); + + } + } + + /** + * Main admin logout as a system user trigger + */ + public function LogoutasObserver() + { + $user = e107::getUser(); + $sysuser = e107::getSystemUser($user->getSessionDataAs(), false); + + if(e107::getUser()->logoutAs() && $sysuser && $sysuser->getId()) + { + // TODO - lan + e107::getMessage()->addSuccess('Successfully logged out from '.$sysuser->getName().' ('.$sysuser->getValue('email').') account', 'default', true); + + $search = array('--UID--', '--NAME--', '--EMAIL--', '--ADMIN_UID--', '--ADMIN_NAME--', '--ADMIN_EMAIL--'); + $replace = array($sysuser->getId(), $sysuser->getName(), $sysuser->getValue('email'), $user->getId(), $user->getName(), $user->getValue('email')); + + // TODO - lan + $lan = 'Administrator --ADMIN_EMAIL-- (#--ADMIN_UID--, --ADMIN_NAME--) has logged out as the user --EMAIL-- (#--UID--, --NAME--)'; + + e107::getAdminLog()->log_event('USET_101', str_replace($search, $replace, $lan), E_LOG_INFORMATIVE); + + $eventData = array('user_id' => $sysuser->getId(), 'admin_id' => $user->getId()); + e107::getEvent()->trigger('logoutas', $eventData); //BC + e107::getEvent()->trigger('admin_user_logoutas', $eventData); + $this->redirect('list', 'main', true); + } + + + if(!$sysuser->getId()) e107::getMessage()->addError(LAN_USER_NOT_FOUND); + } + + public function LogoutasPage() + { + // System Message only on non-successful logout as another user + } + + /** + * Remove admin status trigger + */ + public function ListUnadminTrigger($userid) + { + $user = e107::getUser(); + $sysuser = e107::getSystemUser($userid, false); + $mes = e107::getMessage(); + $tp = e107::getParser(); + + if(!$user->checkAdminPerms('3')) + { + $mes->addError(USRLAN_226, 'default', true); + + //$search = array('--UID--', '--NAME--', '--EMAIL--', '--ADMIN_UID--', '--ADMIN_NAME--', '--ADMIN_EMAIL--'); + $vars = array( + 'u' => $sysuser->getId(), + 'v' => $sysuser->getName(), + 'w' => $sysuser->getValue('email'), + 'x' => $user->getId(), + 'y' => $user->getName(), + 'z' => $user->getValue('email') + ); + + e107::getAdminLog()->log_event('USET_08', $tp->lanVars(USRLAN_244,$vars), E_LOG_INFORMATIVE); + $this->redirect('list', 'main', true); + } + + if ($sysuser->isMainAdmin()) + { + $mes->addError(USRLAN_5); + } + else + { + if($sysuser->set('user_admin', '0')->set('user_perms', '')->save()) + { + $vars = array('x'=>$sysuser->getId(), 'y'=>$sysuser->getName(), 'z'=>$sysuser->getValue('email')); + + e107::getAdminLog()->log_event('USET_09',$tp->lanVars(USRLAN_165, $vars), E_LOG_INFORMATIVE); + $mes->addSuccess($sysuser->getName()." (".$sysuser->getValue('email').") ".USRLAN_6); + $this->getTreeModel()->load(true); + } + else + { + $mes->addError(USRLAN_227); + } + } + } + + /** + * Admin manage observer + * @return void + */ + public function AdminObserver() + { + if($this->getPosted('go_back')) + { + $this->redirect('list', 'main', true); + } + + $userid = $this->getId(); + $sql = e107::getDb(); + $user = e107::getUser(); + $sysuser = e107::getSystemUser($userid, false); + $admin_log = e107::getAdminLog(); + $mes = e107::getMessage(); + $tp = e107::getParser(); + + if(!$user->checkAdminPerms('3')) + { + $mes->addError(USRLAN_226, 'default', true); + // $search = array('--UID--', '--NAME--', '--EMAIL--', '--ADMIN_UID--', '--ADMIN_NAME--', '--ADMIN_EMAIL--'); + + $vars = array( + 'u' => $sysuser->getId(), + 'v' => $sysuser->getName(), + 'w' => $sysuser->getValue('email'), + 'x' => $user->getId(), + 'y' => $user->getName(), + 'z' => $user->getValue('email') + ); + + // $replace = array($sysuser->getId(), $sysuser->getName(), $sysuser->getValue('email'), $user->getId(), $user->getName(), $user->getValue('email')); + + e107::getLog()->add('USET_08', $tp->lanVars( USRLAN_245,$vars), E_LOG_INFORMATIVE); + + $this->redirect('list', 'main', true); + } + + if(!$sysuser->getId()) + { + $mes->addError(USRLAN_223, 'default', true); + $this->redirect('list', 'main', true); + } + + + if($this->getPosted('update_admin')) + { + e107::getUserPerms()->updatePerms($userid, $_POST['perms']); + $this->redirect('list', 'main', true); + } + + if(!$sysuser->isAdmin()) // Security Check Only. Admin status check is added during 'updatePerms'. + { + // $sysuser->set('user_admin', 1)->save(); //"user","user_admin='1' WHERE user_id={$userid}" + // $lan = str_replace(array('--UID--', '--NAME--', '--EMAIL--'), array($sysuser->getId(), $sysuser->getName(), $sysuser->getValue('email')), USRLAN_164); + // e107::getLog()->add('USET_08', $lan, E_LOG_INFORMATIVE); + // $mes->addSuccess($lan); + $rplc_from = array('[x]', '[y]', '[z]'); + $rplc_to = array($sysuser->getId(), $sysuser->getName(), $sysuser->getValue('email')); + $message = str_replace($rplc_from, $rplc_to, USRLAN_228); + $message = e107::getParser()->toHTML($message,true); + $mes->addWarning($message); + $mes->addWarning(e107::getParser()->toHTML(USRLAN_229,true)); + } + + } + + /** + * Admin manage page + */ + public function AdminPage() + { + $request = $this->getRequest(); + $response = $this->getResponse(); + $sysuser = e107::getSystemUser($request->getId(), false); + //$sysuser->load($request->getId(), true); + $prm = e107::getUserPerms(); + $frm = e107::getForm(); + + $response->appendBody($frm->open('adminperms')) + ->appendBody($prm->renderPermTable('grouped', $sysuser->getValue('perms'))) + ->appendBody($prm->renderCheckAllButtons()) + ->appendBody($prm->renderSubmitButtons().$frm->token()) + ->appendBody($frm->close()); + + $this->addTitle(str_replace(array('[x]', '[y]'), array($sysuser->getName(), $sysuser->getValue('email')), USRLAN_230)); + } + + protected function checkAllowed($class_id) // check userclass change is permitted. + { + $e_userclass = e107::getUserClass(); + if (!isset ($e_userclass->class_tree[$class_id])) + { + return false; + } + if (!getperms("0") && !check_class($e_userclass->class_tree[$class_id]['userclass_editclass'])) + { + return false; + } + return true; + } + + protected function manageUserclass($userid, $uclass, $mode = false) + { + $request = $this->getRequest(); + $response = $this->getResponse(); + $sysuser = e107::getSystemUser($userid, false); + + $admin_log = e107::getAdminLog(); + $e_userclass = e107::getUserClass(); + $sql = e107::getDb(); + + $remuser = true; + $mes = e107::getMessage(); + + if(!$sysuser->getId()) + { + $mes->addError(USRLAN_223); + return false; + } + + $curClass = array(); + if($mode !== 'update') + { + $curClass = $sysuser->getValue('class') ? explode(',', $sysuser->getValue('class')) : array(); + } + + foreach ($uclass as $a) + { + $a = intval($a); + if(!$this->checkAllowed($a)) + { + $mes->addError(USRLAN_231); + return false; + } + + if($a != 0) // if 0 - then do not add. + { + $curClass[] = $a; + } + } + + if($mode == "remove") // remove selected classes + { + $curClass = array_diff($curClass, $uclass); + } + elseif($mode == "clear") // clear all classes + { + $curClass = array(); + } + + $curClass = array_unique($curClass); + + $svar = is_array($curClass) ? implode(",", $curClass) : ""; + $check = $sysuser->set('user_class', $svar)->save(); + + if($check) + { + $message = UCSLAN_9; + if ($this->getPosted('notifyuser')) + { + $options = array(); + $message .= "
".UCSLAN_1.": ".$sysuser->getName()."
"; + + $messaccess = ''; + foreach ($curClass as $a) + { + if (!isset ($e_userclass->fixed_classes[$a])) + { + $messaccess .= $e_userclass->class_tree[$a]['userclass_name']." - ".$e_userclass->class_tree[$a]['userclass_description']."\n"; + } + } + if ($messaccess == '') $messaccess = UCSLAN_12."\n"; + + $message = USRLAN_256." ".$sysuser->getName().",\n\n".UCSLAN_4." ".SITENAME."\n( ".SITEURL." )\n\n".UCSLAN_5.": \n\n".$messaccess."\n".UCSLAN_10."\n".SITEADMIN; + // $admin_log->e_log_event(4,__FILE__."|".__FUNCTION__."@".__LINE__,"DBG","User class change",str_replace("\n","
",$message),FALSE,LOG_TO_ROLLING); + + $options['mail_subject'] = UCSLAN_2; + $options['mail_body'] = nl2br($message); + + $sysuser->email('email', $options); + //sendemail($send_to,$subject,$message); + } + e107::getLog()->add('USET_14', str_replace(array('[x]','[y]'), array($userid, $svar), UCSLAN_11), E_LOG_INFORMATIVE); + + $mes->addSuccess(nl2br($message)); + } + else + { + // $mes->add("Update Failed", E_MESSAGE_ERROR); + if($check === false) + { + $sysuser->setMessages(); // move messages to the default stack + } + else + { + $mes->addInfo(LAN_NO_CHANGE); + } + } + } + + /** + * Update user class trigger + */ + public function UserclassUpdateclassTrigger() + { + $this->manageUserclass($this->getId(), $this->getPosted('userclass'), 'update'); + } + + /** + * Back to user list trigger (userclass page) + */ + public function UserclassBackTrigger() + { + $this->redirect('list', 'main', true); + } + + /** + * Manage userclasses page + */ + public function UserclassPage() + { + $request = $this->getRequest(); + $response = $this->getResponse(); + $sysuser = e107::getSystemUser($request->getId(), false); + $e_userclass = e107::getUserClass(); + $userid = $this->getId(); + $frm = e107::getForm(); + + $caption = UCSLAN_6." ".$sysuser->getName().' - '.$sysuser->getValue('email')." (".$sysuser->getClassList(true).")"; + $this->addTitle($caption); + + $text = "
+
+
+ + + + + + + + + + + +
"; + $text .= $e_userclass->vetted_tree('userclass', array($e_userclass,'checkbox_desc'), $sysuser->getValue('class'), 'classes, no-excludes'); + $text .= ' +
+ '; + + $text .= "
+ ".$frm->hidden('userid', $userid)." + ".$frm->checkbox_label(USRLAN_255.'  ', 'notifyuser', 1)." + ".$frm->admin_button('etrigger_updateclass', LAN_NO_RECORDS_FOUND, 'update')." + ".$frm->admin_button('etrigger_back', LAN_BACK, 'cancel')." +
+
+
+
"; + + $response->appendBody($text); + } + + /** + * Resend user activation email trigger + */ + public function ListResendTrigger($userid) + { + $this->resendActivation($userid); + } + + /** + * Resend user activation email helper + * FIXME - better Subject/Content for the activation email when user is bounced/deactivated. + */ + protected function resendActivation($id, $lfile = '') + { + + $sysuser = e107::getSystemUser($id, false); + $key = $sysuser->getValue('sess'); + $mes = e107::getMessage(); + + if(!$sysuser->getId()) + { + $mes->addError(USRLAN_223); + return false; + } + + if(!$key || !$sysuser->getValue('ban')) + { + $mes->addError(USRLAN_232); + $mes->addDebug("key: ".$key." ban: ".$sysuser->getValue('ban')); + return false; + } + + // Check for a Language field, and if present, send the email in the user's language. + // FIXME - make all system emails to be created from HTML email templates, this should fix the multi-lingual issue when sending multiple emails + if ($lfile == "") + { + $lan = $sysuser->getValue('language'); + if ($lan) + { + $lfile = e_LANGUAGEDIR.$lan.'/lan_signup.php'; + } + } + if ($lfile && is_readable($lfile)) + { + require_once($lfile); + } + else + { + //@FIXME use email templates by Language + require_once (e_LANGUAGEDIR.e_LANGUAGE."/lan_signup.php"); + } + if(!$lan) $lan = e_LANGUAGE; + + // FIXME switch to e107::getUrl()->create(), use email content templates + //$return_address = (substr(SITEURL,- 1) == "/") ? SITEURL."signup.php?activate.".$sysuser->getId().".".$key : SITEURL."/signup.php?activate.".$sysuser->getId().".".$key; + $return_address = SITEURL."signup.php?activate.".$sysuser->getId().".".$key; + // $message = LAN_EMAIL_01." ".$sysuser->getName()."\n\n".LAN_SIGNUP_24." ".SITENAME.".\n".LAN_SIGNUP_21."\n\n"; + // $message .= "".$return_address.""; + + + $userInfo = array( + 'user_id' => $sysuser->getId(), + 'user_name' => $sysuser->getName(), + 'user_email' => $sysuser->getValue('email'), + 'user_sess' => $key, + 'user_loginname' => $sysuser->getValue('loginname'), + ); + + + $passwordInput = e107::getPref('signup_option_password', 2); + + if(empty($passwordInput)) // auto-generated password at signup. + { + $newPwd = e107::getUserSession()->resetPassword($userInfo['user_id']); + } + else + { + $newPwd = '**********'; + } + + $message = 'null'; + + $check = $sysuser->email('signup', array( + 'mail_subject' => LAN_SIGNUP_98, + 'mail_body' => nl2br($message), + 'user_password' => $newPwd + ), $userInfo); + + if ($check) + { + $vars = array('x'=> $sysuser->getId(), 'y'=>$sysuser->getName(), 'z'=> $sysuser->getValue('email')); + $message = e107::getParser()->lanVars(USRLAN_167,$vars); + e107::getLog()->add('USET_11', $message, E_LOG_INFORMATIVE); + $mes->addSuccess(USRLAN_140.": ".$sysuser->getName()." (".$sysuser->getValue('email').") ({$lan}) "); + } + else + { + $mes->addError(USRLAN_141.": ".$sysuser->getName().' ('.$sysuser->getValue('email').')'); + } + return $check; + } + + /** + * Test user email observer + */ + public function TestObserver() + { + $sysuser = e107::getSystemUser($this->getId(), false); + $mes = e107::getMessage(); + $email = $sysuser->getValue('email'); + + if(!$sysuser->getId()) + { + $mes->addError(USRLAN_223, 'default', true); + $this->redirect('list', 'main', true); + } + + $result = $this->testEmail($email); + if($result) + { + $this->setParam('testSucces', $result); + $mes->addSuccess($email.' - '.USRLAN_233); + } + else + { + $mes->addError($email.' - '.USRLAN_234, 'default', true); // Invalid. + $this->redirect('list', 'main', true); + } + + } + + public function TestCancelTrigger() + { + $this->redirect('list', 'main', true); + } + + /** + * Resend activation email page - only if tested email is valid + */ + public function TestPage() + { + $response = $this->getResponse(); + $sysuser = e107::getSystemUser($this->getId(), false); + $userid = $this->getId(); + $email = $sysuser->getValue('email'); + $frm = e107::getForm(); + + $caption = str_replace('[x]', $email, USRLAN_119); + $this->addTitle($caption); + + $text = "".LAN_BACK.""; + $text .= '
'.htmlspecialchars($this->getParam('testSucces')).'
'; + $text .= "
+
+
+
+ ".$frm->hidden('useraction', 'resend')." + ".$frm->hidden('userid', $userid)." + ".$frm->hidden('userip', $sysuser->getValue('ip'))." + ".$frm->admin_button('resend', USRLAN_112, 'update')." +
+
+
+
"; + + $response->appendBody($text); + } + + /** + * Test user email helper + */ + protected function testEmail($email) + { + list($adminuser,$adminhost) = explode('@',SITEADMINEMAIL, 2); + + $validator = new email_validation_class; + $validator->localuser = $adminuser; + $validator->localhost = $adminhost; + $validator->timeout = 5; + $validator->debug = 1; + $validator->html_debug = 0; + + ob_start(); + $email_status = $validator->ValidateEmailBox($email); + $text = ob_get_contents(); + ob_end_clean(); + + if ($email_status == 1) + { + return $text; + } + + return false; + } + + /** + * Set user status to require verification - available for bounced users + */ + public function ListReqverifyTrigger($userid) + { + $sysuser = e107::getSystemUser($userid, false); + + if(!$sysuser->getId()) + { + e107::getMessage()->addError(USRLAN_223, 'default', true); + return; + } + + $sysuser->set('user_ban', 2) + ->set('user_sess', e_user_model::randomKey()); + + if($sysuser->save()) + { + e107::getMessage()->addSuccess(USRLAN_235); + + // TODO - auto-send email or not - discuss + $this->resendActivation($userid); + + //FIXME admin log + + // Reload tree + $this->getTreeModel()->load(true); + return; + } + + e107::getMessage()->addError(USRLAN_236); + } + + public function EditSubmitTrigger() + { + $this->_manageSubmit('beforeUpdate', 'afterUpdate', 'onUpdateError', 'edit', true); // force update. + } + + + + /** + * Quick Add user submit trigger + */ + public function AddSubmitTrigger() + { + $e107cache = e107::getCache(); + $userMethods = e107::getUserSession(); + $mes = e107::getMessage(); + $sql = e107::getDb(); + $e_event = e107::getEvent(); + $admin_log = e107::getAdminLog(); + $pref = e107::getPref(); + + if (!$_POST['ac'] == md5(ADMINPWCHANGE)) + { + exit; + } + + $e107cache->clear('online_menu_member_total'); + $e107cache->clear('online_menu_member_newest'); + $error = false; + + if (isset ($_POST['generateloginname'])) + { + $_POST['loginname'] = $userMethods->generateUserLogin($pref['predefinedLoginName']); + } + + $_POST['password2'] = $_POST['password1'] = $_POST['password']; + + // Now validate everything + $allData = validatorClass::validateFields($_POST, $userMethods->userVettingInfo, true); + + // Fix Display and user name + if (!check_class($pref['displayname_class'], $allData['data']['user_class'])) + { + if ($allData['data']['user_name'] != $allData['data']['user_loginname']) + { + $allData['data']['user_name'] = $allData['data']['user_loginname']; + $message = str_replace('[x]', $allData['data']['user_loginname'], USRLAN_237); + $message = e107::getParser()->toHTML($message,true); + $mes->addWarning($message); + //$allData['errors']['user_name'] = ERR_FIELDS_DIFFERENT; + } + } + + // Do basic validation + validatorClass::checkMandatory('user_name, user_loginname', $allData); + + // Check for missing fields (email done in userValidation() ) + validatorClass::dbValidateArray($allData, $userMethods->userVettingInfo, 'user', 0); + + // Do basic DB-related checks + $userMethods->userValidation($allData); + + // Do user-specific DB checks + if (!isset($allData['errors']['user_password'])) + { + // No errors in password - keep it outside the main data array + $savePassword = $allData['data']['user_password']; + // Delete the password value in the output array + unset ($allData['data']['user_password']); + } + + // Restrict the scope of this + unset($_POST['password2'], $_POST['password1']); + + if (count($allData['errors'])) + { + $temp = validatorClass::makeErrorList($allData, 'USER_ERR_','%n - %x - %t: %v', '
', $userMethods->userVettingInfo); + $mes->addError($temp); + $error = true; + } + + // Always save some of the entered data - then we can redisplay on error + $user_data = & $allData['data']; + + if($error) + { + $this->setParam('user_data', $user_data); + return; + } + + if(varset($_POST['perms'])) + { + $allData['data']['user_admin'] = 1; + $allData['data']['user_perms'] = implode('.',$_POST['perms']); + } + + + + $user_data['user_password'] = $userMethods->HashPassword($savePassword, $user_data['user_loginname']); + $user_data['user_join'] = time(); + + e107::getMessage()->addDebug("Password Hash: ".$user_data['user_password']); + + if ($userMethods->needEmailPassword()) + { + // Save separate password encryption for use with email address + $user_prefs = e107::getArrayStorage()->unserialize($user_data['user_prefs']); + $user_prefs['email_password'] = $userMethods->HashPassword($savePassword, $user_data['user_email']); + $user_data['user_prefs'] = e107::getArrayStorage()->serialize($user_prefs); + unset($user_prefs); + } + + $userMethods->userClassUpdate($allData['data'], 'userall'); + + //FIXME - (SecretR) there is a better way to fix this (missing default value, sql error in strict mode - user_realm is to be deleted from DB later) + $allData['data']['user_realm'] = ''; + + // Set any initial classes + $userMethods->addNonDefaulted($user_data); + validatorClass::addFieldTypes($userMethods->userVettingInfo, $allData); + + $userid = $sql->insert('user', $allData); + if ($userid) + { + $this->saveExtended(array('submit_value'=>$userid)); + + $sysuser = e107::getSystemUser(false, false); + $sysuser->setData($allData['data']); + $sysuser->setId($userid); + $user_data['user_id'] = $userid; + + // Add to admin log + e107::getLog()->add('USET_02',"UName: {$user_data['user_name']}; Email: {$user_data['user_email']}", E_LOG_INFORMATIVE); + + // Add to user audit trail + e107::getLog()->user_audit(USER_AUDIT_ADD_ADMIN, $user_data, 0, $user_data['user_loginname']); + e107::getEvent()->trigger('userfull', $user_data); + e107::getEvent()->trigger('admin_user_created', $user_data); + + // send everything available for user data - bit sparse compared with user-generated signup + if(isset($_POST['sendconfemail'])) + { + $check = false; + + // Send confirmation email to user + switch ((int) $_POST['sendconfemail']) + { + case 0: + // activate, don't notify + $check = -1; + break; + + case 1: + // activate and send password + $check = $sysuser->email('quickadd', array( + 'user_password' => $savePassword, + 'mail_subject' => USRLAN_187, + 'activation_url' => USRLAN_246, + )); + break; + + case 2: + // require activation and send password and activation link + $sysuser->set('user_ban', 2) + ->set('user_sess', e_user_model::randomKey()) + ->save(); + + $check = $sysuser->email('quickadd', array( + 'user_password' => $savePassword, + 'mail_subject' => USRLAN_187, + 'activation_url' => SITEURL."signup.php?activate.".$sysuser->getId().".".$sysuser->getValue('sess'), + )); + break; + } + + if($check && $check !== -1) + { + $mes->addSuccess(USRLAN_188); + } + elseif(!$check) + { + $mes->addError(USRLAN_189); + } + } + + // $message = str_replace('--NAME--', htmlspecialchars($user_data['user_name'], ENT_QUOTES, CHARSET), USRLAN_174); + $message = USRLAN_172; // "User account has been created with the following:" ie. keep it simple so it can easily be copied and pasted. + + // Always show Login name and password + //if (isset($_POST['generateloginname'])) + { + $mes->addSuccess($message) + ->addSuccess(USRLAN_128.': '.htmlspecialchars($user_data['user_loginname'], ENT_QUOTES, CHARSET).''); + } + + //if (isset($_POST['generatepassword'])) + { + $mes->addSuccess(LAN_PASSWORD.': '.htmlspecialchars($savePassword, ENT_QUOTES, CHARSET).''); + } + return; + } + else + { + $mes->addError(LAN_CREATED_FAILED); + $mes->addError($sql->getLastErrorText()); + } + } + + /** + * Quick add user page + */ + function AddPage() + { + $prm = e107::getUserPerms(); + //$list = $prm->getPermList(); + $frm = e107::getForm(); + $e_userclass = e107::getUserClass(); + $pref = e107::getPref(); + $user_data = $this->getParam('user_data'); + + // $this->addTitle(LAN_USER_QUICKADD); + + $text = "
".$frm->open("core-user-adduser-form",null,null,'autocomplete=0')." +
+
+ + + + + + + + + + + + + + + + + + + + + + + + "; + + + + $text .= " + + + + + + + + + "; + + if (!isset ($user_data['user_class'])) $user_data['user_class'] = varset($pref['initial_user_classes']); + $temp = $e_userclass->vetted_tree('class', array($e_userclass, 'checkbox_desc'), $user_data['user_class'], 'classes, no-excludes'); + + if ($temp) + { + $text .= " + + + \n"; + } + + // Make Admin. + $text .= " + + + + + "; + + + $text .= " + +
".USRLAN_61." + ".$frm->text('username', varset($user_data['user_name']), varset($pref['displayname_maxlength'], 15), array('size'=>'xlarge'))." +
".USRLAN_128."
+ ".$frm->text('loginname', varset($user_data['user_loginname']), varset($pref['loginname_maxlength'], 30), array('size'=>'xlarge'))."   + ".$frm->checkbox_label(USRLAN_170, 'generateloginname', 1, varset($pref['predefinedLoginName'], false))." +
".USRLAN_129." + ".$frm->text('realname', varset($user_data['user_login']), 30, array('size'=>'xlarge'))." +
".LAN_PASSWORD."".$frm->password('password', '', 128, array('size' => 'xlarge', 'class' => 'tbox e-password', 'generate' => 1, 'strength' => 1, 'autocomplete' => 'new-password'))." +
".USRLAN_64." + ".$frm->text('email', varset($user_data['user_email']), 100, array('size'=>'xlarge'))." +
".USRLAN_239." + ".$frm->select('sendconfemail', array('0' => USRLAN_240, '1' => USRLAN_241, '2' => USRLAN_242), (int) varset($_POST['sendconfemail'], 0), array('size'=>'xlarge'))." +
".USRLAN_181."
+
+ ".USRLAN_120." + + ".USRLAN_120." +
+ {$temp} +
+
".USRLAN_35." + ".USRLAN_243." +
+ "; + + $text .= $prm->renderPermTable('grouped'); + + $text .= " +
+
+
+ ".$frm->admin_trigger('submit', USRLAN_60, 'create')." + ".$frm->token()." + +
+
+ +
+ "; + + + return $text; + //$ns->tablerender(USRLAN_59,$mes->render().$text); + } + + public function RanksUpdateTrigger() + { + $fg = array(); + $ranks_calc = ''; + $ranks_flist = ''; + $config = e107::getConfig(); + foreach ($_POST['op'] as $f => $o) + { + $cfg[$f]['op'] = $o; + $cfg[$f]['val'] = varset($_POST['val'][$f],''); + if ($_POST['val'][$f]) + { + $ranks_calc .= ($ranks_calc ? ' + ' : '').'({'.$f.'} '." $o {$_POST['val'][$f]}".' )'; + $ranks_flist .= ($ranks_flist ? ',' : '').$f; + } + } + + //Delete existing rank config + e107::getDb()->delete('generic', "gen_type = 'user_rank_config'"); + + $tmp = array(); + $tmp['data']['gen_type'] = 'user_rank_config'; + $tmp['data']['gen_chardata'] = serialize($cfg); + $tmp['_FIELD_TYPES']['gen_type'] = 'string'; + $tmp['_FIELD_TYPES']['gen_chardata'] = 'escape'; + + //Add the new rank config + e107::getDb()->insert('generic', $tmp); + + // save prefs + $config->set('ranks_calc', $ranks_calc); + $config->set('ranks_flist', $ranks_flist); + $config->save(); + $config->resetMessages(); + + //Delete existing rank data + e107::getDb()->delete('generic',"gen_type = 'user_rank_data'"); + + //Add main site admin info + $tmp = array(); + $tmp['_FIELD_TYPES']['gen_datestamp'] = 'int'; + $tmp['_FIELD_TYPES']['gen_ip'] = 'todb'; + $tmp['_FIELD_TYPES']['gen_user_id'] = 'int'; + $tmp['_FIELD_TYPES']['gen_chardata'] = 'todb'; + $tmp['_FIELD_TYPES']['gen_intdata'] = 'int'; + $tmp['data']['gen_datestamp'] = 1; + $tmp['data']['gen_type'] = 'user_rank_data'; + $tmp['data']['gen_ip'] = $_POST['calc_name']['main_admin']; + $tmp['data']['gen_user_id'] = varset($_POST['calc_pfx']['main_admin'],0); + $tmp['data']['gen_chardata'] = $_POST['calc_img']['main_admin']; + e107::getDb()->insert('generic',$tmp); + + //Add site admin info + unset ($tmp['data']); + $tmp['data']['gen_type'] = 'user_rank_data'; + $tmp['data']['gen_datestamp'] = 2; + $tmp['data']['gen_ip'] = $_POST['calc_name']['admin']; + $tmp['data']['gen_user_id'] = varset($_POST['calc_pfx']['admin'],0); + $tmp['data']['gen_chardata'] = $_POST['calc_img']['admin']; + e107::getDb()->insert('generic', $tmp); + + //Add all current site defined ranks + if (isset ($_POST['field_id'])) + { + foreach ($_POST['field_id'] as $fid => $x) + { + unset ($tmp['data']); + $tmp['data']['gen_type'] = 'user_rank_data'; + $tmp['data']['gen_ip'] = varset($_POST['calc_name'][$fid],''); + $tmp['data']['gen_user_id'] = varset($_POST['calc_pfx'][$fid],0); + $tmp['data']['gen_chardata'] = varset($_POST['calc_img'][$fid],''); + $tmp['data']['gen_intdata'] = varset($_POST['calc_lower'][$fid],'_NULL_'); + e107::getDb()->insert('generic', $tmp); + } + } + + //Add new rank, if posted + if (varset($_POST['new_calc_lower'])) + { + unset ($tmp['data']); + $tmp['data']['gen_type'] = 'user_rank_data'; + $tmp['data']['gen_datestamp'] = 0; + $tmp['data']['gen_ip'] = varset($_POST['new_calc_name']); + $tmp['data']['gen_user_id'] = varset($_POST['new_calc_pfx'],0); + $tmp['data']['gen_chardata'] = varset($_POST['new_calc_img']); + $tmp['data']['gen_intdata'] = varset($_POST['new_calc_lower']); + e107::getDb()->insert('generic', $tmp); + } + + e107::getMessage()->addSuccess(LAN_UPDATED); //XXX maybe not needed see pull/1816 + e107::getCache()->clear_sys('nomd5_user_ranks'); + } + + function RanksDeleteTrigger($posted) + { + $rankId = (int) key($posted); + + e107::getCache()->clear_sys('nomd5_user_ranks'); + if (e107::getDb()->delete('generic',"gen_id='{$rankId}'")) + { + e107::getMessage()->addSuccess(LAN_DELETED); + } + else + { + e107::getMessage()->addError(LAN_DELETED_FAILED); + } + } + + function RanksPage() + { + $frm = e107::getForm(); + $e107 = e107::getInstance(); + $pref = e107::getPref(); + $mes = e107::getMessage(); + /** @var users_admin_form_ui $ui */ + $ui = $this->getUI(); + $tp = e107::getParser(); + + $ranks = e107::getRank()->getRankData(); + $tmp = e107::getFile()->get_files(e_IMAGE.'ranks', '.*?\.(png|gif|jpg)'); + + // $this->addTitle(LAN_USER_RANKS); + + foreach($tmp as $k => $v) + { + $imageList[] = $v['fname']; + } + unset($tmp); + natsort($imageList); + + $text = $frm->open('core-user-ranks-form'); + + + $fields = array( + 'type' => array('title' => USRLAN_207, 'type' => 'text', 'width' => 'auto', 'thclass' => 'left', 'class' => 'left'), + 'rankName' => array('title' => USRLAN_208, 'type' => 'text', 'width' => 'auto', 'thclass' => 'left', 'class' => 'left'), + 'lowThresh' => array('title' => USRLAN_209, 'type' => 'text', 'width' => 'auto', 'thclass' => 'left', 'class' => 'left'), + 'langPrefix' => array('title' => USRLAN_210, 'type' => 'text', 'width' => 'auto', 'thclass' => 'left', 'class' => 'left'), + 'rankImage' => array('title' => USRLAN_211, 'type' => 'text', 'width' => 'auto', 'thclass' => 'left', 'class' => 'left'), + ); + + + $text .= " + ". + $frm->colGroup($fields, array_keys($fields)). + $frm->thead($fields, array_keys($fields)); + + $info = $ranks['special'][1]; + $val = $tp->toForm($info['name']); + $text .= " + + + + + + + + "; + $info = $ranks['special'][2]; + $val = $tp->toForm($info['name']); + $text .= " + + + + + + + + + + + "; + + foreach ($ranks['data'] as $k => $r) + { + $pfx_checked = ($r['lan_pfx'] ? "checked='checked'" : ''); + $text .= " + + + + + + + + "; + } + + $text .= " + + + + + + + + + + + "; + + $text .= '
".LAN_MAINADMIN." + ".$frm->text('calc_name[main_admin]', $val)." + N/A".$frm->checkbox('calc_pfx[main_admin]', 1, $info['lan_pfx'] ? true : false)."".$ui->RankImageDropdown($imageList,'calc_img[main_admin]',$info['image'])."
".LAN_ADMIN." + ".$frm->text('calc_name[admin]', $val)." + N/A".$frm->checkbox('calc_pfx[admin]', 1, $info['lan_pfx'] ? true : false)."".$ui->RankImageDropdown($imageList, 'calc_img[admin]', $info['image'])."
 
".USRLAN_212." + + + ".$frm->number("calc_lower[{$k}]", $r['thresh'])."".$frm->checkbox("calc_pfx[{$k}]", 1, $r['lan_pfx'] ? true : false)."".$ui->RankImageDropdown($imageList, "calc_img[$k]", $r['image'])." ". + $frm->submit_image("etrigger_delete[{$r['id']}]", LAN_DELETE, 'delete', LAN_CONFIRMDEL.": [{$r['name']}]?")." +
 
".USRLAN_214."".$frm->text('new_calc_name', '')."".$frm->number('new_calc_lower', '')."".$frm->checkbox('new_calc_pfx', 1, false)."".$ui->RankImageDropdown($imageList, 'new_calc_img')."
+
+ '.$frm->admin_trigger('update', 'no-value', 'update', LAN_UPDATE).' +
+ '; + + return $text; + } + + // ================== OLD CODE backup =============> + + // It might be rewritten with user info option (ui trigger) + // Old trigger code + // if ((isset ($_POST['useraction']) && $_POST['useraction'] == "userinfo") || $_GET['userinfo']) + // { + // $ip = ($_POST['userip']) ? $_POST['userip'] : $_GET['userinfo']; + // $user->user_info($ip); + // } + function user_info($ipd) + { + global $ns, $sql, $e107; + + if (isset($ipd)) + { + $bullet = ''; + if(defined('BULLET')) + { + $bullet = ''; + } + elseif(file_exists(THEME.'images/bullet2.gif')) + { + $bullet = ''; + } + // TODO - move to e_userinfo.php + $obj = new convert; + $sql->db_Select("chatbox", "*", "cb_ip='$ipd' LIMIT 0,20"); + $host = $e107->get_host_name($ipd); + $text = USFLAN_3." ".$ipd." [ ".USFLAN_4.": $host ]
+ ".USFLAN_5." + +

"; + while (list($cb_id, $cb_nick, $cb_message, $cb_datestamp, $cb_blocked, $cb_ip ) = $sql->fetch()) + { + $datestamp = $obj->convert_date($cb_datestamp, "short"); + $post_author_id = substr($cb_nick, 0, strpos($cb_nick, ".")); + $post_author_name = substr($cb_nick, (strpos($cb_nick, ".")+1)); + $text .= $bullet." + ".$post_author_name." (".USFLAN_6.": ".$post_author_id.") +
+ ".$datestamp." +
+ ". $cb_message." +
+
"; + } + + $text .= "
"; + + $sql->db_Select("comments", "*", "comment_ip='$ipd' LIMIT 0,20"); + while (list($comment_id, $comment_item_id, $comment_author, $comment_author_email, $comment_datestamp, $comment_comment, $comment_blocked, $comment_ip) = $sql->fetch()) + { + $datestamp = $obj->convert_date($comment_datestamp, "short"); + $post_author_id = substr($comment_author, 0, strpos($comment_author, ".")); + $post_author_name = substr($comment_author, (strpos($comment_author, ".")+1)); + $text .= $bullet." + ".$post_author_name." (".USFLAN_6.": ".$post_author_id.") +
+ ".$datestamp." +
". $comment_comment." +
+
"; + } + + } + + $ns->tablerender(USFLAN_7, $text); + } + + + + + function maintenancePage() + { + $frm = e107::getForm(); + $ns = e107::getRender(); + $sql = e107::getDb(); + $tp = e107::getParser(); + + $age = array( + 1=> LAN_UI_1_HOUR, 3=> LAN_UI_3_HOURS, 6=> LAN_UI_6_HOURS, 12=> LAN_UI_12_HOURS, 24 => LAN_UI_24_HOURS, 48 => LAN_UI_48_HOURS, 72 => LAN_UI_3_DAYS); + + $count = $sql->count('user','(*)',"user_ban = 2 "); + $caption = $tp->lanVars(USRLAN_252,$count); + + $text = $frm->open('userMaintenance','post'); + + $text .= " + + + + + + +
".$caption." + +
".USRLAN_253." ".$frm->select('resendAge', $age, 24).$frm->checkbox('resetPasswords',1,false,USRLAN_254). + "
".$frm->userclass('resendClass',false, null )."". + $frm->button('resendToAll', 1, 'warning', LAN_GO)." + + +
"; + + $text .= $frm->close(); + + return $text; + + + + + } + + + /** + * Send an activation email to all unactivated users older than so many hours. + * @param bool $resetPasswords + * @param int $age in hours. ie. older than 24 hours will be sent an email. + */ + function resend_to_all($resetPasswords=false, $age=24, $class='') + { + global $sql,$pref; + $tp = e107::getParser(); + $sql = e107::getDb(); + $sql2 = e107::getDb('toall'); + + $emailLogin = e107::getPref('allowEmailLogin'); + + e107::lan('core','signup'); + + $ageOpt = intval($age)." hours ago"; + $age = strtotime($ageOpt); + + // $query = "SELECT u.*, ue.* FROM `#user` AS u LEFT JOIN `#user_extended` AS ue ON ue.user_extended_id = u.user_id WHERE u.user_ban = 2 AND u.user_email != '' AND u.user_join < ".$age." ORDER BY u.user_id DESC"; + + + $query = "SELECT u.* FROM `#user` AS u WHERE u.user_ban = 2 AND u.user_email != '' AND u.user_join < ".$age." "; + + if(!empty($class)) + { + $query .= " AND FIND_IN_SET( ".intval($class).", u.user_class) "; + } + + $query .= " ORDER BY u.user_id DESC"; + + $sql->gen($query); + + $recipients = array(); + + $usr = e107::getUserSession(); + + while ($row = $sql->fetch()) + { + + if($resetPasswords === true) + { + $rawPassword = $usr->generateRandomString('********'); + $sessKey = e_user_model::randomKey(); + + $updateQry = array( + 'user_sess' => $sessKey, + 'user_password' => $usr->HashPassword($rawPassword, $row['user_loginname']), + 'WHERE' => 'user_id = '.$row['user_id']." LIMIT 1" + ); + + if(!$sql2->update('user',$updateQry)) + { + + e107::getMessage()->addError("Error updating user's password. #".$row['user_id']." : ".$row['user_email']); + e107::getMessage()->addDebug(print_a($updateQry,true)); + + // break; + } + else + { + e107::getMessage()->addInfo("Updated ".$row['user_id']." : ".$row['user_email']); + } + + + $row['user_sess'] = $sessKey; + + } + else + { + $rawPassword = '(*** hidden ***)'; + } + + $activationUrl = SITEURL."signup.php?activate.".$row['user_id'].".".$row['user_sess']; + + + + $recipients[] = array( + 'mail_recipient_id' => $row['user_id'], + 'mail_recipient_name' => $row['user_name'], // Should this use realname? + 'mail_recipient_email' => $row['user_email'], + 'mail_target_info' => array( + 'USERID' => $row['user_id'], + 'LOGINNAME' => (intval($emailLogin) === 1) ? $row['user_email'] : $row['user_loginname'], + 'PASSWORD' => $rawPassword, + 'DISPLAYNAME' => $tp->toDB($row['user_name']), + 'SUBJECT' => LAN_SIGNUP_98, + 'USERNAME' => $row['user_name'], + 'USERLASTVISIT' => $row['user_lastvisit'], + 'ACTIVATION_LINK' => ''.$activationUrl.'', // Warning: switching the quotes on this will break the template. + 'ACTIVATION_URL' => $activationUrl, + 'DATE_SHORT' => $tp->toDate(time(),'short'), + 'DATE_LONG' => $tp->toDate(time(),'long'), + 'SITEURL' => SITEURL + ) + ); + + // echo $row['user_id']." ".$row['user_sess']." ".$row['user_name']." ".$row['user_email']."
"; + + } + + $siteadminemail = e107::getPref('siteadminemail'); + $siteadmin = e107::getPref('siteadmin'); + + $mailer = e107::getBulkEmail(); + + // Create the mail body + $mailData = array( + 'mail_total_count' => count($recipients), + 'mail_content_status' => MAIL_STATUS_TEMP, + 'mail_create_app' => 'core', + 'mail_title' => 'RESEND ACTIVATION', + 'mail_subject' => LAN_SIGNUP_98, + 'mail_sender_email' => e107::getPref('replyto_email',$siteadminemail), + 'mail_sender_name' => e107::getPref('replyto_name',$siteadmin), + 'mail_notify_complete' => 0, // NEVER notify when this email sent!!!!! + 'mail_body' => 'null', + 'template' => 'signup', + 'mail_send_style' => 'signup' + ); + + + $mailer->sendEmails('signup', $mailData, $recipients, array('mail_force_queue'=>1)); + $totalMails = count($recipients); + + $url = e_ADMIN."mailout.php?mode=pending&action=list"; + + e107::getMessage()->addSuccess("Total emails added to mail queue: ".$totalMails); + + } + + // --------------------------------------------------------------------- + // Bounce handling - FIXME convert to cron job + // --------------------------------------------------------------------- + // $bounce_act has the task to perform: + // 'first_check' - initial read of list of bounces + // 'delnonbounce' - delete any emails that aren't bounces + // 'clearemailbounce' - delete email address for any user whose emails bounced + // 'delchecked' - delete the emails whose comma-separated IDs are in $bounce_arr + // 'delall' - delete all bounced emails + + /* + function check_bounces($bounce_act = 'first_check',$bounce_arr = '') + { + ### old Trigger code for bounce check + // $bounce_act = ''; + // if (isset ($_POST['check_bounces'])) + // $bounce_act = 'first_check'; + // if (isset ($_POST['delnonbouncesubmit'])) + // $bounce_act = 'delnonbounce'; + // if (isset ($_POST['clearemailbouncesubmit'])) + // $bounce_act = 'clearemailbounce'; + // if (isset ($_POST['delcheckedsubmit'])) + // $bounce_act = 'delchecked'; + // if (isset ($_POST['delallsubmit'])) + // $bounce_act = 'delall'; + // if ($bounce_act) + // { + // $user->check_bounces($bounce_act,implode(',',$_POST['delete_email'])); + // require_once ("footer.php"); + // exit; + // } + + global $sql,$pref; + include (e_HANDLER.'pop3_class.php'); + if (!trim($bounce_act)) + { + $bounce_act = 'first_check'; + } + // echo "Check bounces. Action: {$bounce_act}; Entries: {$bounce_arr}
"; + $obj = new receiveMail($pref['mail_bounce_user'],$pref['mail_bounce_pass'],$pref['mail_bounce_email'],$pref['mail_bounce_pop3'],varset($pref['mail_bounce_type'],'pop3')); + $del_count = 0; + if ($bounce_act != 'first_check') + { + // Must do some deleting + $obj->connect(); + $tot = $obj->getTotalMails(); + $del_array = explode(',',$bounce_arr); + for ($i = 1; $i <= $tot; $i++) + { + // Scan all emails; delete current one if meets the criteria + $dodel = false; + switch ($bounce_act) + { + case 'delnonbounce' : + $head = $obj->getHeaders($i); + $dodel = (!$head['bounce']); + break; + case 'clearemailbounce' : + if (!in_array($i,$del_array)) + break; + $head = $obj->getHeaders($i); + if ($head['bounce']) + { + if (preg_match("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i",$obj->getBody($i),$result)) + { + $usr_email = trim($result[0]); + } + if ($sql->db_Select('user','user_id, user_name, user_email',"user_email='".$usr_email."' ")) + { + $row = $sql->fetch(); + if ($sql->db_Update('user',"`user_email`='' WHERE `user_id` = '".$row['user_id']."' ") !== false) + { + // echo "Deleting user email {$row['user_email']} for user {$row['user_name']}, id={$row['user_id']}
"; + $dodel = true; + } + } + } + break; + case 'delall' : + $dodel = true; + break; + case 'delchecked' : + $dodel = in_array($i,$del_array); + break; + } + if ($dodel) + { + // echo "Delete email ID {$i}
"; + $obj->deleteMails($i); + $del_count++; + // Keep track of number of emails deleted + } + } + // End - Delete one email + $obj->close_mailbox(); + // This actually deletes the emails + } + // End of email deletion + // Now list the emails that are left + $obj->connect(); + $tot = $obj->getTotalMails(); + $found = false; + $DEL = ($pref['mail_bounce_delete']) ? true : false; + $text = "
+ \n"; + + $identifier = deftrue('MAIL_IDENTIFIER', 'X-e107-id'); + + for ($i = 1; $i <= $tot; $i++) + { + $head = $obj->getHeaders($i); + if ($head['bounce']) + { + // Its a 'bounce' email + if (preg_match('/.*'.$identifier.':(.*)MIME/',$obj->getBody($i),$result)) + { + if ($result[1]) + { + $id[$i] = intval($result[1]); + // This should be a user ID - but not on special mailers! + // Try and pull out an email address from body - should be the one that failed + if (preg_match("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i",$obj->getBody($i),$result)) + { + $emails[$i] = "'".$result[0]."'"; + } + $found = true; + } + } + elseif (preg_match("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i",$obj->getBody($i),$result)) + { + if ($result[0] && $result[0] != $pref['mail_bounce_email']) + { + $emails[$i] = "'".$result[0]."'"; + $found = true; + } + elseif ($result[1] && $result[1] != $pref['mail_bounce_email']) + { + $emails[$i] = "'".$result[1]."'"; + $found = true; + } + } + if ($DEL && $found) + { + // Auto-delete bounced emails once noticed (if option set) + $obj->deleteMails($i); + $del_count++; + } + } + else + { + // Its a warning message or similar + // $id[$i] = ''; // Don't worry about an ID for now + // Try and pull out an email address from body - should be the one that failed + if (preg_match("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i",$obj->getBody($i),$result)) + { + $wmails[$i] = "'".$result[0]."'"; + } + } + $text .= "\n"; + } + if ($del_count) + { + e107::getLog()->add('USET_13', e107::getParser()->lanVars(USRLAN_169, $del_count),E_LOG_INFORMATIVE); + } + if ($tot) + { + // Option to delete emails - only if there are some in the list + $text .= "
#e107-idemailSubjectBounce
".$i."".$id[$i]."".(isset ($emails[$i]) ? $emails[$i] : $wmails[$i])."".$head['subject']."".($head['bounce'] ? ADMIN_TRUE_ICON : ADMIN_FALSE_ICON); + $text .= "
+ \n + \n + \n + \n + "; + } + $text .= "
"; + array_unique($id); + array_unique($emails); + $all_ids = implode(',',$id); + $all_emails = implode(',',$emails); + $obj->close_mailbox(); + // This will actually delete emails + // $tot has total number of emails in the mailbox + $found = count($emails); + // $found - Number of bounce emails found + // $del_count has number of emails deleted + // Update bounce status for users + $ed = $sql->db_Update('user',"user_ban=3 WHERE (`user_id` IN (".$all_ids.") OR `user_email` IN (".$all_emails.")) AND user_sess !='' "); + if (!$ed) + $ed = '0'; + $this->show_message(str_replace(array('[w]','[x]','[y]','[z]'),array($tot,$del_count,$ed,$found),USRLAN_155).$text); + } + */ +// ------- FIXME Prune Users move to cron -------------- +// if (isset ($_POST['prune'])) +// { + // $e107cache->clear('online_menu_member_total'); + // $e107cache->clear('online_menu_member_newest'); + // $text = USRLAN_56.' '; + // $bantype = $_POST['prune_type']; + // if ($bantype == 30) + // // older than 30 days. + // { + // $bantype = 2; + // $ins = " AND user_join < ".strtotime("-30 days"); + // } + // if ($sql->db_Select("user","user_id, user_name","user_ban= {$bantype}".$ins)) + // { + // $uList = $sql->db_getList(); + // foreach ($uList as $u) + // { + // $text .= $u['user_name']." "; + // $sql->db_Delete("user","user_id='{$u['user_id']}' "); + // $sql->db_Delete("user_extended","user_extended_id='{$u['user_id']}' "); + // } + // e107::getLog()->add('USET_04',str_replace(array('[x]','--TYPE--'),array(count($uList),$bantype),USRLAN_160),E_LOG_INFORMATIVE); + // } + // $ns->tablerender(USRLAN_57,"
".$text."
"); + // unset ($text); +// } +} + + +class users_admin_form_ui extends e_admin_form_ui +{ + + + function user_admin($curval,$mode, $att) + { + $att['type'] = 'boolean'; + +// $uid = $this->getController()->getModel()->get('user_id'); + $perms = $this->getController()->getModel()->get('user_perms'); + + if($mode == 'filter' && getperms('3')) + { + return array(0=>LAN_NO, '1'=>LAN_YES); + } + + if($mode == 'read' || (str_replace(".","",$perms) == '0') || !getperms('3')) + { + return $this->renderValue('user_admin',$curval,$att); + } + + if($mode == 'write') + { + return $this->renderElement('user_admin',$curval,$att); + } + + + + } + + + function user_extended($curval,$mode, $att) + { + if($mode == 'read') + { + $field = $att['field']; + + if($this->getController()->getAction() == 'list') + { + $data = $this->getController()->getListModel()->get($field); // ($att['field']); + } + else + { + $data = $this->getController()->getModel()->get($field); // ($att['field']); + } + + + + return e107::getUserExt()->renderValue($data, $att['ueType']); + + + } + if($mode == 'write') + { + // e107::getUserExt()->user_extended_edit + // return 'hello'; + $field = $att['field']; + /** @var users_admin_ui $controller */ + $controller = $this->getController(); + $extData = $controller->getExtended(); + $extData[$field]['user_extended_struct_required'] = 0; + + return e107::getUserExt()->user_extended_edit($extData[$field],$curval); + + // return print_a($att,true); + } + + + } + + + + + + function user_perms($curval,$mode) + { + $perms = $this->getController()->getModel()->get('user_perms'); + $uid = $this->getController()->getModel()->get('user_id'); + + if($mode == 'read' || (str_replace(".","",$perms) == '0' && $uid == USERID) || !getperms('3')) + { + return e107::getUserPerms()->renderPerms($curval,$uid); + } + if($mode == 'write') + { + $prm = e107::getUserPerms(); + $text = "".USRLAN_221.""; + $text .= "'; + return $text; + } + + + } + + function user_password($curval,$mode) + { + if($mode == 'read') + { + if(empty($curval)) + { + return "No password!"; + } + + // if(getperms('0')) + { + + $type = e107::getUserSession()->getHashType($curval, 'array'); + $num = $type[0]; + + $styles= array(0=>'label-danger',1=>'label-warning', 3=>'label-success'); + + return "".$type[1].""; + } + } + if($mode == 'write') + { + $fieldName = 'user_password_'. $this->getController()->getId(); + + return $this->password($fieldName, '', 128, array('size' => 50, 'class' => 'tbox e-password', 'placeholder' => USRLAN_251, 'generate' => 1, 'strength' => 1, 'required'=>0, 'autocomplete'=>'new-password')); + } + + + } + + + + + + + function user_ban($curval,$mode) + { + $bo = array( + ''.LAN_ACTIVE.'', + "".LAN_BANNED."", + "".LAN_NOTVERIFIED."", + "".LAN_BOUNCED."", + "".USRLAN_56."", // Deleted + ); + + if($mode == 'filter' || $mode == 'batch') + { + return $bo; + } + + $perms = $this->getController()->getModel()->get('user_perms'); + + if($mode == 'write') + { + + if(str_replace(".","",$perms) == '0') + { + return "
".vartrue($bo[$curval],' ')."
"; + } + + return $this->select('user_ban',$bo,$curval); + } + + return vartrue($bo[$curval],' '); // ($curval == 1) ? ADMIN_TRUE_ICON : ''; + } + + + /* + function user_class($curval,$mode) + { + + $e_userclass = new user_class; + $frm = e107::getForm(); + $list = $e_userclass->uc_required_class_list("classes"); + if($mode == 'filter') + { + return $list; + } + + if($mode == 'write') //FIXME userclasses are NOT be saved since they are an array. + { + return $frm->select('user_class', $list, $curval, 'description=1&multiple=1'); + // return $frm->uc_select('user_class[]', $curval, 'admin,classes', 'description=1&multiple=1');// doesn't work correctly. + } + + + //FIXME TODO - option to append userclass to existing value. + if($mode == 'batch') + { + //$list['#delete'] = "(clear userclass)"; // special + return $list; + } + $tmp = explode(",",$curval); + $text = array(); + foreach($tmp as $v) + { + $text[] = $list[$v]; + } + return implode("
",$text); // $list[$curval]; + + }*/ + + + /* + function user_status($curval,$mode) + { + + $row = $this->getController()->getListModel()->getData(); + + $text = ""; + if ($row['user_perms'] == "0") + { + $text .= "
".LAN_MAINADMIN."
"; + } + else + if ($row['user_admin']) + { + $text .= ""; + } + else + if ($row['user_ban'] == 1) + { + $text .= ""; + } + else + if ($row['user_ban'] == 2) + { + $text .= "
".LAN_NOTVERIFIED."
"; + } + else + if ($row['user_ban'] == 3) + { + $text .= "
".LAN_BOUNCED."
"; + } + else + { + $text .= " "; + } + + return $text; + + + } + */ + + //TODO Reduce to simple edit/delete buttons only Other options included on edit page or available via inline or batch editing. + function options($val, $mode) // old drop-down options. + { + $controller = $this->getController(); + + if($controller->getMode() != 'main' || $controller->getAction() != 'list') return; + $row = $controller->getListModel()->getData(); + + if(!getperms('4')) + { + // return; + } + + + // extract($row); + + $user_id = intval($row['user_id']); + $user_ip = $row['user_ip']; + $user_admin = $row['user_admin']; + + $head = "
+ + + + + "; + + // "; + // $foot = "
"; + + $btn = '
+ + +
'; + + if(!empty($opts)) + { + return $head.$btn; + } + else + { + return ''; + } + + // return ($text) ? $head.$text.$foot . $btn : ""; + } + + + function RankImageDropdown(&$imgList, $field, $curVal = '') + { + $ret = " + '; + return $ret; + } + + +} + + + class users_ranks_ui extends e_admin_ui + { + protected $pluginTitle = ADLAN_36; + protected $pluginName = 'user_ranks'; + protected $table = 'generic'; + protected $pid = 'gen_id'; + protected $perPage = 15; + protected $listQry = "SELECT * FROM `#generic` WHERE gen_type='user_rank_data' "; + protected $listOrder = " CASE gen_datestamp WHEN 1 THEN 1 WHEN 2 THEN 2 WHEN 3 THEN 3 WHEN 0 THEN 4 END, gen_intdata "; + + protected $fields = array ( + 'checkboxes' => array ( 'title' => '', 'type' => null, 'data' => null, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect', ), + 'gen_id' => array ( 'title' => LAN_ID, 'nolist'=>true, 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'gen_type' => array ( 'title' => LAN_BAN, 'type' => 'hidden', 'data' => 'str', 'width' => 'auto', 'batch' => true, 'filter' => true, 'inline' => true, 'help' => '', 'readParms' => '', 'writeParms' => 'value=user_rank_data', 'class' => 'left', 'thclass' => 'left', ), + 'gen_ip' => array ( 'title' => USRLAN_208, 'type' => 'text', 'data' => 'str', 'inline'=>true, 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'gen_intdata' => array ( 'title' => USRLAN_209, 'type' => 'text', 'batch'=>false, 'data' => 'int', 'inline'=>true, 'width' => 'auto', 'help' => '', 'readParms' => 'default=-', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), + + 'gen_datestamp' => array ( 'title' => 'Special', 'type' => 'hidden', 'nolist'=>true, 'data' => 'int', 'width' => 'auto', 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'gen_user_id' => array ( 'title' => USRLAN_210, 'type' => 'boolean', 'batch'=>true, 'data' => 'int', 'inline'=>true, 'width' => '15%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'center', 'thclass' => 'center', ), + //'gen_chardata' => array ( 'title' => LAN_ICON, 'type' => 'dropdown', 'data' => 'str', 'inline'=>true, 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => array(), 'class' => 'left', 'thclass' => 'left', ), + 'gen_chardata' => array ( 'title' => LAN_ICON, 'type' => 'method', 'data' => 'str', 'inline'=>true, 'width' => 'auto', 'help' => '', 'readParms' => array(), 'writeParms' => array(), 'class' => 'left', 'thclass' => 'left', ), + + + 'options' => array ( 'title' => LAN_OPTIONS, 'type' =>'method', 'data' => null, 'width' => '10%', 'thclass' => 'center last', 'class' => 'right last', 'forced' => '1', 'readParms'=>'edit=0' ), + ); + + protected $fieldpref = array('gen_datestamp', 'gen_type', 'gen_ip', 'gen_intdata', 'gen_user_id', 'gen_chardata'); + + + // optional + public function init() + { + $tmp = e107::getFile()->get_files(e_IMAGE.'ranks', '.*?\.(png|gif|jpg)'); + + $mode = $this->getMode(); + $action = $this->getAction(); + + $existing = e107::getDb()->gen("SELECT gen_id FROM #generic WHERE gen_type='user_rank_data' LIMIT 1 "); + + if($mode == 'ranks' && ($action == 'list') && !$existing) + { + $this->createDefaultRecords(); + } + + // $this->addTitle(LAN_USER_RANKS); + + foreach($tmp as $k => $v) + { + $id = $v['fname']; + $this->fields['gen_chardata']['writeParms']['optArray'][$id] = $v['fname']; + } + + unset($tmp); + // natsort($imageList); + } + + public function afterDelete($data, $id, $deleted_check) + { + e107::getCache()->clear_sys('nomd5_user_ranks'); + } + + public function afterUpdate($new_data, $old_data, $id) + { + e107::getCache()->clear_sys('nomd5_user_ranks'); + } + + private function createDefaultRecords() + { + + $tmp = array(); + $tmp['_FIELD_TYPES']['gen_datestamp'] = 'int'; + $tmp['_FIELD_TYPES']['gen_ip'] = 'todb'; + $tmp['_FIELD_TYPES']['gen_user_id'] = 'int'; + $tmp['_FIELD_TYPES']['gen_chardata'] = 'todb'; + $tmp['_FIELD_TYPES']['gen_intdata'] = 'int'; + + + //Add main site admin info + $tmp['data']['gen_datestamp'] = 1; + $tmp['data']['gen_type'] = 'user_rank_data'; + $tmp['data']['gen_ip'] = LAN_MAINADMIN; + $tmp['data']['gen_user_id'] = 1; + $tmp['data']['gen_chardata'] = 'English_main_admin.png'; + $tmp['data']['gen_intdata'] = 0; + e107::getDb()->insert('generic',$tmp); + unset ($tmp['data']); + + + //Add site admin info + $tmp['data']['gen_type'] = 'user_rank_data'; + $tmp['data']['gen_datestamp'] = 2; + $tmp['data']['gen_ip'] = LAN_ADMIN; + $tmp['data']['gen_user_id'] = 1; + $tmp['data']['gen_chardata'] = 'English_admin.png'; + $tmp['data']['gen_intdata'] = 0; + + + e107::getDb()->insert('generic', $tmp); + + for($i=1; $i < 11; $i++) + { + unset ($tmp['data']); + $tmp['data']['gen_type'] = 'user_rank_data'; + $tmp['data']['gen_datestamp'] = 0; + $tmp['data']['gen_ip'] = "Level ".$i; + $tmp['data']['gen_user_id'] = 0; + $tmp['data']['gen_chardata'] = "lev".$i.".png"; + $tmp['data']['gen_intdata'] = ($i * 150); + + e107::getDb()->insert('generic', $tmp); + } + + + + } + + } + + + + class users_ranks_ui_form extends e_admin_form_ui + { + // Override the default Options field. + function options($parms, $value, $id, $attributes) + { + + if($attributes['mode'] == 'read') + { + parse_str(str_replace('&', '&', e_QUERY), $query); + $query['action'] = 'edit'; + $query['id'] = $id; + $query = http_build_query($query, null, '&'); + + $text = " + ".ADMIN_EDIT_ICON.""; + + $special = $this->getController()->getListModel()->get('gen_datestamp'); + + if($special == 0) + { + $text .= $this->submit_image('menu_delete['.$id.']', $id, 'delete', LAN_DELETE.' [ ID: '.$id.' ]', array('class' => 'action delete btn btn-default')); + } + + return $text; + } + } + + function gen_chardata($curVal, $mode, $parms=null) + { + switch($mode) + { + case 'read': + return '
'.$curVal; + break; + + case 'write': + $opts = $this->getController()->getFields()['gen_chardata']['writeParms']['optArray']; + return e107::getForm()->select('gen_chardata', $opts, $curVal); + + case 'filter': + case 'batch': + return null; + break; + + } + } + + + } + + + +new users_admin(); +require_once ('auth.php'); + +e107::getAdminUI()->runPage(); + +require_once ("footer.php"); diff --git a/e107_core/bbcodes/b.bb b/e107_core/bbcodes/b.bb index 7852cde33..43c3d9f4d 100644 --- a/e107_core/bbcodes/b.bb +++ b/e107_core/bbcodes/b.bb @@ -1,4 +1,4 @@ -//getClass('b'); -return "$code_text"; +//getClass('b'); +return "$code_text"; diff --git a/e107_core/bbcodes/bb_block.php b/e107_core/bbcodes/bb_block.php index fcdb04cd4..9775e961b 100644 --- a/e107_core/bbcodes/bb_block.php +++ b/e107_core/bbcodes/bb_block.php @@ -1,63 +1,63 @@ -' - */ -class bb_block extends e_bb_base -{ - /** - * Called prior to save - * - */ - function toDB($code_text, $parm) - { - // just for now - if(!ADMIN) return $code_text; // TODO - pref - - // transform to class, equal sign at 0 position is not well formed parm string - if($parm && !strpos($parm, '=')) $parm = 'class='.$parm; - $parms = eHelper::scParams($parm); - $safe = array(); - - if(vartrue($parms['class'])) $safe['class'] = eHelper::secureClassAttr($parms['class']); - if(vartrue($parms['id'])) $safe['id'] = eHelper::secureIdAttr($parms['id']); - if(vartrue($parms['style'])) $safe['style'] = eHelper::secureStyleAttr($parms['style']); - if($safe) - { - return '[block='.eHelper::buildAttr($safe).']'.$code_text.'[/block]'; - } - return '[block]'.$code_text.'[/block]'; - } - - /** - * Translate youtube bbcode into the appropriate HTML - */ - function toHTML($code_text, $parm) - { - // transform to class, equal sign at 0 position is not well formed parm string - if($parm && !strpos($parm, '=')) $parm = 'class='.$parm; - $parms = eHelper::scParams($parm); - - // add auto-generated class name and parameter class if available - $class = e107::getBB()->getClass('block').(varset($parms['class']) ? ' '.$parms['class'] : ''); - $class = ' class="'.$class.'"'; - - $id = vartrue($parms['id']) ? ' id="'.eHelper::secureIdAttr($parms['id']).'"' : ''; - $style = vartrue($parms['style']) ? ' style="'.eHelper::secureStyleAttr($parms['style']).'"' : ''; - - if(empty($code_text)) $code_text = ''; - return ''.$code_text.''; - } -} +' + */ +class bb_block extends e_bb_base +{ + /** + * Called prior to save + * + */ + function toDB($code_text, $parm) + { + // just for now + if(!ADMIN) return $code_text; // TODO - pref + + // transform to class, equal sign at 0 position is not well formed parm string + if($parm && !strpos($parm, '=')) $parm = 'class='.$parm; + $parms = eHelper::scParams($parm); + $safe = array(); + + if(vartrue($parms['class'])) $safe['class'] = eHelper::secureClassAttr($parms['class']); + if(vartrue($parms['id'])) $safe['id'] = eHelper::secureIdAttr($parms['id']); + if(vartrue($parms['style'])) $safe['style'] = eHelper::secureStyleAttr($parms['style']); + if($safe) + { + return '[block='.eHelper::buildAttr($safe).']'.$code_text.'[/block]'; + } + return '[block]'.$code_text.'[/block]'; + } + + /** + * Translate youtube bbcode into the appropriate HTML + */ + function toHTML($code_text, $parm) + { + // transform to class, equal sign at 0 position is not well formed parm string + if($parm && !strpos($parm, '=')) $parm = 'class='.$parm; + $parms = eHelper::scParams($parm); + + // add auto-generated class name and parameter class if available + $class = e107::getBB()->getClass('block').(varset($parms['class']) ? ' '.$parms['class'] : ''); + $class = ' class="'.$class.'"'; + + $id = vartrue($parms['id']) ? ' id="'.eHelper::secureIdAttr($parms['id']).'"' : ''; + $style = vartrue($parms['style']) ? ' style="'.eHelper::secureStyleAttr($parms['style']).'"' : ''; + + if(empty($code_text)) $code_text = ''; + return ''.$code_text.''; + } +} diff --git a/e107_core/bbcodes/bb_h.php b/e107_core/bbcodes/bb_h.php index 111e5abb1..99fc8bf5f 100644 --- a/e107_core/bbcodes/bb_h.php +++ b/e107_core/bbcodes/bb_h.php @@ -1,75 +1,75 @@ - tag - */ - function toHTML($code_text, $parm) - { - $code_text = trim($code_text); - if(empty($code_text)) return ''; - $bparms = eHelper::scDualParams($parm); - - $h = 'h'.($bparms[1] ? intval($bparms[1]) : 2); - $parms = $bparms[2]; - unset($bparms); - - $class = " class='".e107::getBB()->getClass($h)."'"; // consistent classes across all themes. - - $id = vartrue($parms['id']) ? ' id='.eHelper::secureIdAttr($parms['id']) : ''; - $style = vartrue($parms['style']) ? ' style="'.eHelper::secureStyleAttr($parms['style']).'"' : ''; - - return "<{$h}{$id}{$class}{$style}>".$code_text.""; - } -} + tag + */ + function toHTML($code_text, $parm) + { + $code_text = trim($code_text); + if(empty($code_text)) return ''; + $bparms = eHelper::scDualParams($parm); + + $h = 'h'.($bparms[1] ? intval($bparms[1]) : 2); + $parms = $bparms[2]; + unset($bparms); + + $class = " class='".e107::getBB()->getClass($h)."'"; // consistent classes across all themes. + + $id = vartrue($parms['id']) ? ' id='.eHelper::secureIdAttr($parms['id']) : ''; + $style = vartrue($parms['style']) ? ' style="'.eHelper::secureStyleAttr($parms['style']).'"' : ''; + + return "<{$h}{$id}{$class}{$style}>".$code_text.""; + } +} diff --git a/e107_core/bbcodes/bb_nobr.php b/e107_core/bbcodes/bb_nobr.php index 2ef2bf7df..379be3254 100644 --- a/e107_core/bbcodes/bb_nobr.php +++ b/e107_core/bbcodes/bb_nobr.php @@ -1,35 +1,35 @@ - tag - */ - function toHTML($code_text, $parm) - { - if($parm && !strpos($parm, '=')) $parm = 'class='.$parm; - $code_text = trim($code_text); - - $parms = eHelper::scParams($parm); - - $class = " ".e107::getBB()->getClass('p'); // consistent classes across all themes. - - $id = vartrue($parms['id']) ? ' id="'.eHelper::secureIdAttr($parms['id']).'"' : ''; - $style = vartrue($parms['style']) ? ' style="'.eHelper::secureStyleAttr($parms['style']).'"' : ''; - - return "".$code_text.'

'; - } -} + tag + */ + function toHTML($code_text, $parm) + { + if($parm && !strpos($parm, '=')) $parm = 'class='.$parm; + $code_text = trim($code_text); + + $parms = eHelper::scParams($parm); + + $class = " ".e107::getBB()->getClass('p'); // consistent classes across all themes. + + $id = vartrue($parms['id']) ? ' id="'.eHelper::secureIdAttr($parms['id']).'"' : ''; + $style = vartrue($parms['style']) ? ' style="'.eHelper::secureStyleAttr($parms['style']).'"' : ''; + + return "".$code_text.'

'; + } +} diff --git a/e107_core/bbcodes/bb_youtube.php b/e107_core/bbcodes/bb_youtube.php index b1638391b..dcb888e0a 100644 --- a/e107_core/bbcodes/bb_youtube.php +++ b/e107_core/bbcodes/bb_youtube.php @@ -1,370 +1,370 @@ -Parm= '.$parm; - echo "
COde= ".htmlspecialchars($code_text); - echo "
Width= ".$widthString; - */ - - $params = array(); // Accumulator for parameters from youtube code - $ok = 0; - if (strpos($code_text, '<') === FALSE) - { // 'Properly defined' bbcode (we hope) - $picRef = $code_text; - } - else - { - //libxml_use_internal_errors(TRUE); - if (FALSE === ($info = simplexml_load_string($code_text))) - { - //print_a($matches); - //$xmlErrs = libxml_get_errors(); - //print_a($xmlErrs); - $ok = 1; - } - else - { - $info1 = (array)$info; - if (!isset($info1['embed'])) - { - $ok = 2; - } - else - { - $info2 = (array)$info1['embed']; - if (!isset($info2['@attributes'])) - { - $ok = 3; - } - } - } - if ($ok != 0) - { - print_a($info); - return '[sanitised]'.$ok.'B'.htmlspecialchars($matches[0]).'B[/sanitised]'; - } - $target = (array)$info2['@attributes']; - unset($info); - $ws = varset($target['width'], 0); - $hs = varset($target['height'], 0); - if (($ws == 0) || ($hs == 0) || !isset($target['src'])) return '[sanitised]A'.htmlspecialchars($matches[0]).'A[/sanitised]'; - if (!$widthString) - { - $widthString = $ws.','.$hs; // Set size of window - } - list($url, $query) = explode('?', $target['src']); - if (strpos($url, 'youtube-nocookie.com') !== FALSE) - { - $bb_params[] = 'privacy'; - } - - parse_str($query, $vals); // Various options set here - - if (varset($vals['allowfullscreen'], 'true') != 'true') - { - $params[] = 'fs=0'; - } - if (varset($vals['border'], 0) != 0) - { - $params[] = 'border=1'; - } - if (varset($vals['rel'], 1) != 1) - { - $params[] = 'rel='.intval($vals['rel']); - } - if (varset($vals['hd'], 1) != 0) - { - $params[] = 'hd='.intval($vals['hd']); - } - if (varset($vals['hl'], 1) != 0) - { - $params[] = 'hl='.$vals['hl']; - } - if (varset($vals['color1'], 1) != 0) - { - $params[] = 'color1='.$vals['color1']; - } - if (varset($vals['color2'], 1) != 0) - { - $params[] = 'color2='.$vals['color2']; - } - if (varset($vals['cc_load_policy'], 1) != 0) - { - $params[] = 'cc_load_policy='.intval($vals['cc_load_policy']); - } - if (ADMIN && varset($vals['autoplay'], 1) != 0) - { - $params[] = 'autoplay='.intval($vals['autoplay']); - } - - $picRef = substr($url, strrpos($url, '/') + 1); - } - - - $yID = preg_replace('/[^0-9a-z]/i', '', $picRef); - if (($yID != $picRef) || (strlen($yID) > 20)) - { // Possible hack attempt - } - // $params = array_merge($params, $bbpars); // Any parameters set in bbcode override those in HTML - // Could check for valid array indices here - $paramString = implode('&', $params); - if ($paramString) $picRef .= '?'.$paramString; - if($widthString) - { - $widthString = "=".$widthString; - if(count($bbpars)) - { - $widthString .= "|".implode("&",$bbpars); - } - } - $ans = '[youtube'.$widthString.']'.$picRef.'[/youtube]'; - return $ans; - } - - - - /** - * Translate youtube bbcode into the appropriate object - */ - function toHTML($code_text, $parm) - { - if(empty($code_text)) return ''; - - list($dimensions,$tmp) = explode('|', $parm, 2); - - if($tmp) - { - parse_str(varset($tmp, ''), $bbparm); - } - - if(strpos($code_text,"&")!==FALSE && strpos($code_text,"?")===FALSE) // DEPRECATED - { - $parms = explode('&', $code_text, 2); - } - else - { - $parms = explode('?', $code_text, 2); // CORRECT SEPARATOR - } - - - $code_text = $parms[0]; - - parse_str(varset($parms[1], ''), $params); - - // print_a($params); - - if(empty($dimensions)) $dimensions = 'medium'; // (default as per YouTube spec) - // formula: width x (height+25px) - - switch ($dimensions) - { - case 'tiny': - $params['w'] = 320; // 200; - $params['h'] = 205; // 180; - break; - - case 'small': - $params['w'] = 560; // 445; - $params['h'] = 340; // 364; - break; - - case 'medium': - $params['w'] = 640; // 500; - $params['h'] = 385; // 405; - break; - - case 'big': - case 'large': - $params['w'] = 853; // 660; - $params['h'] = 505; // 525; - break; - - case 'huge': - $params['w'] = 1280; // 980; - $params['h'] = 745; // 765; - break; - - default: // maximum 1920 x 1080 (+25) - $dim = explode(',', $dimensions, 2); - $params['w'] = (integer) varset($dim[0], 445); - if($params['w'] > 1920 || $params['w'] < 100) $params['w'] = 640; - - $params['h'] = (integer) varset($dim[1], 364); - if($params['h'] > 1105 || $params['h'] < 67) $params['h'] = 385; - break; - } - - - $yID = preg_replace('/[^0-9a-z\-_\&\?]/i', '', $code_text); - - $url = isset($bbparm['privacy']) ? 'https://www.youtube-nocookie.com/v/' : 'https://www.youtube.com/v/'; - $url .= $yID.'?'; - - if(isset($params['nofull']) || !varset($params['fs'])) - { - $fscr = 'false'; - $url = $url.'fs='.intval($params['fs']); - } - else - { - $fscr = 'true'; - $url = $url.'fs=1'; - } - - - - if(isset($params['border'])) $url = $url.'&border='.intval($params['border']); - if(isset($params['norel'])) // BC non-standard val. - { - $url = $url.'&rel=0'; - } - elseif(isset($params['rel'])) - { - $url = $url.'&rel='.intval($params['rel']); - } - - if(isset($params['hd'])) $url = $url.'&hd='.intval($params['hd']); - - $hl = 'en_US'; - - if(isset($params['hl'])) - { - $params['hl'] = preg_replace('/[^0-9a-z\-_]/i', '', $params['hl']); - if(strlen($params['hl']) == 2 || strlen($params['hl']) == 5) - { - $hl = $params['hl']; - } - } - - $url = $url.'&hl='.$hl; - $color = array(); - if(isset($params['color1'])) $color[1] = $params['color1']; - if(isset($params['color2'])) $color[2] = $params['color2']; - foreach ($color as $key => $value) - { - if (ctype_xdigit($value) && strlen($value) == 6) - { - $url = $url.'&color'.$key.'='.$value; - } - } - - if(isset($params['cc_load_policy'])) - { - $url .= "&cc_load_policy=".intval($params['cc_load_policy']); - } - - if(isset($params['autoplay'])) - { - $url .= "&autoplay=".intval($params['autoplay']); - } - - $class = "bbcode ".e107::getBB()->getClass('youtube'); // consistent classes across all themes. - - $ret = "\n"; // <-- DO NOT MODIFY - used for detection by bbcode handler. - - - if(e107::getConfig()->get('youtube_bbcode_responsive') == 1) // Responsive Mode. - { - $ret .= e107::getParser()->toVideo($yID.".youtube"); - } - else // Legacy Mode. - { - $ret .= ' - - - - - '; - - // Not XHTML - but needed for compatibility. - $ret .= ''; - - $ret .= ''; - } - - $ret .= ""; // <-- DO NOT MODIFY. - - - return $ret; - } - - // Wysiwyg representation of bbcode render. - function toWYSIWYG($code_text,$parm) - { - //eg. an image of the video thumbnail - } -} - +Parm= '.$parm; + echo "
COde= ".htmlspecialchars($code_text); + echo "
Width= ".$widthString; + */ + + $params = array(); // Accumulator for parameters from youtube code + $ok = 0; + if (strpos($code_text, '<') === FALSE) + { // 'Properly defined' bbcode (we hope) + $picRef = $code_text; + } + else + { + //libxml_use_internal_errors(TRUE); + if (FALSE === ($info = simplexml_load_string($code_text))) + { + //print_a($matches); + //$xmlErrs = libxml_get_errors(); + //print_a($xmlErrs); + $ok = 1; + } + else + { + $info1 = (array)$info; + if (!isset($info1['embed'])) + { + $ok = 2; + } + else + { + $info2 = (array)$info1['embed']; + if (!isset($info2['@attributes'])) + { + $ok = 3; + } + } + } + if ($ok != 0) + { + print_a($info); + return '[sanitised]'.$ok.'B'.htmlspecialchars($matches[0]).'B[/sanitised]'; + } + $target = (array)$info2['@attributes']; + unset($info); + $ws = varset($target['width'], 0); + $hs = varset($target['height'], 0); + if (($ws == 0) || ($hs == 0) || !isset($target['src'])) return '[sanitised]A'.htmlspecialchars($matches[0]).'A[/sanitised]'; + if (!$widthString) + { + $widthString = $ws.','.$hs; // Set size of window + } + list($url, $query) = explode('?', $target['src']); + if (strpos($url, 'youtube-nocookie.com') !== FALSE) + { + $bb_params[] = 'privacy'; + } + + parse_str($query, $vals); // Various options set here + + if (varset($vals['allowfullscreen'], 'true') != 'true') + { + $params[] = 'fs=0'; + } + if (varset($vals['border'], 0) != 0) + { + $params[] = 'border=1'; + } + if (varset($vals['rel'], 1) != 1) + { + $params[] = 'rel='.intval($vals['rel']); + } + if (varset($vals['hd'], 1) != 0) + { + $params[] = 'hd='.intval($vals['hd']); + } + if (varset($vals['hl'], 1) != 0) + { + $params[] = 'hl='.$vals['hl']; + } + if (varset($vals['color1'], 1) != 0) + { + $params[] = 'color1='.$vals['color1']; + } + if (varset($vals['color2'], 1) != 0) + { + $params[] = 'color2='.$vals['color2']; + } + if (varset($vals['cc_load_policy'], 1) != 0) + { + $params[] = 'cc_load_policy='.intval($vals['cc_load_policy']); + } + if (ADMIN && varset($vals['autoplay'], 1) != 0) + { + $params[] = 'autoplay='.intval($vals['autoplay']); + } + + $picRef = substr($url, strrpos($url, '/') + 1); + } + + + $yID = preg_replace('/[^0-9a-z]/i', '', $picRef); + if (($yID != $picRef) || (strlen($yID) > 20)) + { // Possible hack attempt + } + // $params = array_merge($params, $bbpars); // Any parameters set in bbcode override those in HTML + // Could check for valid array indices here + $paramString = implode('&', $params); + if ($paramString) $picRef .= '?'.$paramString; + if($widthString) + { + $widthString = "=".$widthString; + if(count($bbpars)) + { + $widthString .= "|".implode("&",$bbpars); + } + } + $ans = '[youtube'.$widthString.']'.$picRef.'[/youtube]'; + return $ans; + } + + + + /** + * Translate youtube bbcode into the appropriate object + */ + function toHTML($code_text, $parm) + { + if(empty($code_text)) return ''; + + list($dimensions,$tmp) = explode('|', $parm, 2); + + if($tmp) + { + parse_str(varset($tmp, ''), $bbparm); + } + + if(strpos($code_text,"&")!==FALSE && strpos($code_text,"?")===FALSE) // DEPRECATED + { + $parms = explode('&', $code_text, 2); + } + else + { + $parms = explode('?', $code_text, 2); // CORRECT SEPARATOR + } + + + $code_text = $parms[0]; + + parse_str(varset($parms[1], ''), $params); + + // print_a($params); + + if(empty($dimensions)) $dimensions = 'medium'; // (default as per YouTube spec) + // formula: width x (height+25px) + + switch ($dimensions) + { + case 'tiny': + $params['w'] = 320; // 200; + $params['h'] = 205; // 180; + break; + + case 'small': + $params['w'] = 560; // 445; + $params['h'] = 340; // 364; + break; + + case 'medium': + $params['w'] = 640; // 500; + $params['h'] = 385; // 405; + break; + + case 'big': + case 'large': + $params['w'] = 853; // 660; + $params['h'] = 505; // 525; + break; + + case 'huge': + $params['w'] = 1280; // 980; + $params['h'] = 745; // 765; + break; + + default: // maximum 1920 x 1080 (+25) + $dim = explode(',', $dimensions, 2); + $params['w'] = (integer) varset($dim[0], 445); + if($params['w'] > 1920 || $params['w'] < 100) $params['w'] = 640; + + $params['h'] = (integer) varset($dim[1], 364); + if($params['h'] > 1105 || $params['h'] < 67) $params['h'] = 385; + break; + } + + + $yID = preg_replace('/[^0-9a-z\-_\&\?]/i', '', $code_text); + + $url = isset($bbparm['privacy']) ? 'https://www.youtube-nocookie.com/v/' : 'https://www.youtube.com/v/'; + $url .= $yID.'?'; + + if(isset($params['nofull']) || !varset($params['fs'])) + { + $fscr = 'false'; + $url = $url.'fs='.intval($params['fs']); + } + else + { + $fscr = 'true'; + $url = $url.'fs=1'; + } + + + + if(isset($params['border'])) $url = $url.'&border='.intval($params['border']); + if(isset($params['norel'])) // BC non-standard val. + { + $url = $url.'&rel=0'; + } + elseif(isset($params['rel'])) + { + $url = $url.'&rel='.intval($params['rel']); + } + + if(isset($params['hd'])) $url = $url.'&hd='.intval($params['hd']); + + $hl = 'en_US'; + + if(isset($params['hl'])) + { + $params['hl'] = preg_replace('/[^0-9a-z\-_]/i', '', $params['hl']); + if(strlen($params['hl']) == 2 || strlen($params['hl']) == 5) + { + $hl = $params['hl']; + } + } + + $url = $url.'&hl='.$hl; + $color = array(); + if(isset($params['color1'])) $color[1] = $params['color1']; + if(isset($params['color2'])) $color[2] = $params['color2']; + foreach ($color as $key => $value) + { + if (ctype_xdigit($value) && strlen($value) == 6) + { + $url = $url.'&color'.$key.'='.$value; + } + } + + if(isset($params['cc_load_policy'])) + { + $url .= "&cc_load_policy=".intval($params['cc_load_policy']); + } + + if(isset($params['autoplay'])) + { + $url .= "&autoplay=".intval($params['autoplay']); + } + + $class = "bbcode ".e107::getBB()->getClass('youtube'); // consistent classes across all themes. + + $ret = "\n"; // <-- DO NOT MODIFY - used for detection by bbcode handler. + + + if(e107::getConfig()->get('youtube_bbcode_responsive') == 1) // Responsive Mode. + { + $ret .= e107::getParser()->toVideo($yID.".youtube"); + } + else // Legacy Mode. + { + $ret .= ' + + + + + '; + + // Not XHTML - but needed for compatibility. + $ret .= ''; + + $ret .= ''; + } + + $ret .= ""; // <-- DO NOT MODIFY. + + + return $ret; + } + + // Wysiwyg representation of bbcode render. + function toWYSIWYG($code_text,$parm) + { + //eg. an image of the video thumbnail + } +} + ?> \ No newline at end of file diff --git a/e107_core/bbcodes/blockquote.bb b/e107_core/bbcodes/blockquote.bb index 1d1529a31..ef777b31e 100644 --- a/e107_core/bbcodes/blockquote.bb +++ b/e107_core/bbcodes/blockquote.bb @@ -1,4 +1,4 @@ -//getClass('blockquote'); - +//getClass('blockquote'); + return "
{$code_text}
"; \ No newline at end of file diff --git a/e107_core/bbcodes/center.bb b/e107_core/bbcodes/center.bb index 3724b50bc..9678da5a9 100644 --- a/e107_core/bbcodes/center.bb +++ b/e107_core/bbcodes/center.bb @@ -1,5 +1,5 @@ -//getClass('center'); - +//getClass('center'); + return "
$code_text
"; \ No newline at end of file diff --git a/e107_core/bbcodes/i.bb b/e107_core/bbcodes/i.bb index ae6959c2c..e59522688 100644 --- a/e107_core/bbcodes/i.bb +++ b/e107_core/bbcodes/i.bb @@ -1,4 +1,4 @@ -//getClass('i'); - +//getClass('i'); + return "$code_text"; \ No newline at end of file diff --git a/e107_core/bbcodes/justify.bb b/e107_core/bbcodes/justify.bb index a3e012628..29fa8f6b8 100644 --- a/e107_core/bbcodes/justify.bb +++ b/e107_core/bbcodes/justify.bb @@ -1,4 +1,4 @@ -//getClass('justify'); - +//getClass('justify'); + return "
$code_text
"; \ No newline at end of file diff --git a/e107_core/bbcodes/sanitised.bb b/e107_core/bbcodes/sanitised.bb index 2f5c2e25c..531669de0 100644 --- a/e107_core/bbcodes/sanitised.bb +++ b/e107_core/bbcodes/sanitised.bb @@ -1,7 +1,7 @@ -/* $Id: sanitised.bb 11660 2010-08-16 16:41:35Z secretr $ */ -// decode (just in case) and re-code sanitised string if debug and ADMIN -if(defsettrue('ADMIN') && defsettrue('E107_DEBUG_LEVEL')) -{ - return ' SANITISED: '.htmlentities(html_entity_decode(rawurldecode($code_text), ENT_QUOTES, CHARSET), ENT_QUOTES, CHARSET).' SANITISED END'; -} +/* $Id: sanitised.bb 11660 2010-08-16 16:41:35Z secretr $ */ +// decode (just in case) and re-code sanitised string if debug and ADMIN +if(defsettrue('ADMIN') && defsettrue('E107_DEBUG_LEVEL')) +{ + return ' SANITISED: '.htmlentities(html_entity_decode(rawurldecode($code_text), ENT_QUOTES, CHARSET), ENT_QUOTES, CHARSET).' SANITISED END'; +} return '##'.LAN_SANITISED.'##'; \ No newline at end of file diff --git a/e107_core/bbcodes/u.bb b/e107_core/bbcodes/u.bb index e3264fd45..d5e0c298e 100644 --- a/e107_core/bbcodes/u.bb +++ b/e107_core/bbcodes/u.bb @@ -1,3 +1,3 @@ -//getClass('u'); +//getClass('u'); return "$code_text"; \ No newline at end of file diff --git a/e107_core/controllers/index/index.php b/e107_core/controllers/index/index.php index 27897e9bf..28aa9f8f2 100644 --- a/e107_core/controllers/index/index.php +++ b/e107_core/controllers/index/index.php @@ -1,185 +1,185 @@ -getPref(); - $tp = e107::getParser(); - $indexRoute = 'index/index/index'; - - if (file_exists(e_BASE.'index_include.php')) - { - include (e_BASE.'index_include.php'); - } - - $location = ''; - $class_list = explode(',', USERCLASS_LIST); - - if (isset($pref['frontpage']['all']) && $pref['frontpage']['all']) - { // 0.7 method - $location = $pref['frontpage']['all']; - } - else - { // This is the 'new' method - assumes $pref['frontpage'] is an ordered list of rules - if(vartrue($pref['frontpage'])) - { - foreach ($pref['frontpage'] as $fk=>$fp) - { - if (in_array($fk, $class_list)) - { - $location = $fp; - break; - } - } - } - } - - if (!$location) - { // Try and use the 'old' method (this bit can go later) - if (ADMIN) - { - $location = $pref['frontpage'][e_UC_ADMIN]; - } - elseif (USER) - { // This is the key bit - what to do for a 'normal' logged in user - // We have USERCLASS_LIST - comma separated. Also e_CLASS_REGEXP - foreach ($class_list as $fp_class) - { - $inclass = false; - if (!$inclass && check_class($fp_class['userclass_id'])) - { - $location = $pref['frontpage'][$fp_class['userclass_id']]; - $inclass = true; - } - } - $location = $location ? $location : $pref['frontpage'][e_UC_MEMBER]; - } - else - { - $location = $pref['frontpage'][e_UC_GUEST]; - } - } - - $location = trim($location); - $request = $this->getRequest(); - - // Defaults to news - if(!$location) $location = 'url:/news'; - // Former Welcome Message front-page. Should be handled by current theme layout - elseif($location == 'index.php' || $location == 'url:/' || $location == 'route:/' || $location == '/') - { - define('e_FRONTPAGE', true); - $this->_forward('front'); - return; - } - elseif($location[0] === '{') - { - $location = $tp->replaceConstants($location, true); - } - - // new url format; if set to 'url:' only it'll resolve current main module (if any) - if(strpos($location, 'url:') === 0) - { - $url = substr($location, 4); - $request->setPathInfo($url)->setRequestParams(array()); - $router = eFront::instance()->getRouter(); - - if($router->route($request, true)) - { - if($request->getRoute() == $indexRoute) - { - throw new eException('Infinite loop detected while dispatching front page.', 2); - } - define('e_FRONTPAGE', true); - $this->_forward($request->getRoute()); - return; - } - $this->_forward('system/error/notfound', array('frontPageErorr' => null)); - } - // route is provided - elseif(strpos($location, 'route:') === 0) - { - list($route, $qstr) = explode('?', substr($location, 6).'?'); - - if(!$qstr) $qstr = array(); - else parse_str($qstr, $qstr); - - $request->setRoute($route); - $request->setRequestParams($qstr); - - if($request->getRoute() == $indexRoute) - { - throw new eException('Infinite loop detected while dispatching front page.', 2); - } - define('e_FRONTPAGE', true); - $this->_forward($request->getRoute(), $qstr); - - return; - } - // redirect to this address - elseif(strpos($location, 'http://') === 0 || strpos($location, 'https://') === 0) - { - if(e_REQUEST_URL != $location) - { - header("Location: {$location}"); - exit; - } - } - // Enter in legacy mod, include the front page - elseif(strpos($location, '.php') !== false) - { - list($page, $qstr) = explode("?", $location."?"); - - $request->setLegacyPage($page) - ->setLegacyQstring($qstr); - - $request->routed = true; - define('e_FRONTPAGE', true); - eFront::isLegacy('{e_BASE}'.$page); - return $this; - } - // Redirect - else - { - $location = SITEURL.$location; - if(e_REQUEST_URL != $location) - { - header("Location: {$location}"); - exit; - } - } - - // we can't do much - $this->_forward('system/error/notfound', array('frontPageErorr' => null)); - } - - public function actionFront() - { - // we could notify current theme we are in front page controlled by the theme layout only... - // switch off tablerender - $this->getResponse()->setParam('render', false); - } -} +getPref(); + $tp = e107::getParser(); + $indexRoute = 'index/index/index'; + + if (file_exists(e_BASE.'index_include.php')) + { + include (e_BASE.'index_include.php'); + } + + $location = ''; + $class_list = explode(',', USERCLASS_LIST); + + if (isset($pref['frontpage']['all']) && $pref['frontpage']['all']) + { // 0.7 method + $location = $pref['frontpage']['all']; + } + else + { // This is the 'new' method - assumes $pref['frontpage'] is an ordered list of rules + if(vartrue($pref['frontpage'])) + { + foreach ($pref['frontpage'] as $fk=>$fp) + { + if (in_array($fk, $class_list)) + { + $location = $fp; + break; + } + } + } + } + + if (!$location) + { // Try and use the 'old' method (this bit can go later) + if (ADMIN) + { + $location = $pref['frontpage'][e_UC_ADMIN]; + } + elseif (USER) + { // This is the key bit - what to do for a 'normal' logged in user + // We have USERCLASS_LIST - comma separated. Also e_CLASS_REGEXP + foreach ($class_list as $fp_class) + { + $inclass = false; + if (!$inclass && check_class($fp_class['userclass_id'])) + { + $location = $pref['frontpage'][$fp_class['userclass_id']]; + $inclass = true; + } + } + $location = $location ? $location : $pref['frontpage'][e_UC_MEMBER]; + } + else + { + $location = $pref['frontpage'][e_UC_GUEST]; + } + } + + $location = trim($location); + $request = $this->getRequest(); + + // Defaults to news + if(!$location) $location = 'url:/news'; + // Former Welcome Message front-page. Should be handled by current theme layout + elseif($location == 'index.php' || $location == 'url:/' || $location == 'route:/' || $location == '/') + { + define('e_FRONTPAGE', true); + $this->_forward('front'); + return; + } + elseif($location[0] === '{') + { + $location = $tp->replaceConstants($location, true); + } + + // new url format; if set to 'url:' only it'll resolve current main module (if any) + if(strpos($location, 'url:') === 0) + { + $url = substr($location, 4); + $request->setPathInfo($url)->setRequestParams(array()); + $router = eFront::instance()->getRouter(); + + if($router->route($request, true)) + { + if($request->getRoute() == $indexRoute) + { + throw new eException('Infinite loop detected while dispatching front page.', 2); + } + define('e_FRONTPAGE', true); + $this->_forward($request->getRoute()); + return; + } + $this->_forward('system/error/notfound', array('frontPageErorr' => null)); + } + // route is provided + elseif(strpos($location, 'route:') === 0) + { + list($route, $qstr) = explode('?', substr($location, 6).'?'); + + if(!$qstr) $qstr = array(); + else parse_str($qstr, $qstr); + + $request->setRoute($route); + $request->setRequestParams($qstr); + + if($request->getRoute() == $indexRoute) + { + throw new eException('Infinite loop detected while dispatching front page.', 2); + } + define('e_FRONTPAGE', true); + $this->_forward($request->getRoute(), $qstr); + + return; + } + // redirect to this address + elseif(strpos($location, 'http://') === 0 || strpos($location, 'https://') === 0) + { + if(e_REQUEST_URL != $location) + { + header("Location: {$location}"); + exit; + } + } + // Enter in legacy mod, include the front page + elseif(strpos($location, '.php') !== false) + { + list($page, $qstr) = explode("?", $location."?"); + + $request->setLegacyPage($page) + ->setLegacyQstring($qstr); + + $request->routed = true; + define('e_FRONTPAGE', true); + eFront::isLegacy('{e_BASE}'.$page); + return $this; + } + // Redirect + else + { + $location = SITEURL.$location; + if(e_REQUEST_URL != $location) + { + header("Location: {$location}"); + exit; + } + } + + // we can't do much + $this->_forward('system/error/notfound', array('frontPageErorr' => null)); + } + + public function actionFront() + { + // we could notify current theme we are in front page controlled by the theme layout only... + // switch off tablerender + $this->getResponse()->setParam('render', false); + } +} diff --git a/e107_core/controllers/system/error.php b/e107_core/controllers/system/error.php index a2a6a51ca..dbf3bafd3 100644 --- a/e107_core/controllers/system/error.php +++ b/e107_core/controllers/system/error.php @@ -1,62 +1,62 @@ -_forward('forbidden'); - } - - /** - * Alias for "Error 404". - */ - public function action404() - { - $this->_forward('notfound'); - } - - /** - * Error 403. - */ - public function actionForbidden() - { - e107::getError()->render(403); - } - - /** - * Error 404. - */ - public function actionNotfound() - { - e107::getError()->render(404); - } - -} +_forward('forbidden'); + } + + /** + * Alias for "Error 404". + */ + public function action404() + { + $this->_forward('notfound'); + } + + /** + * Error 403. + */ + public function actionForbidden() + { + e107::getError()->render(403); + } + + /** + * Error 404. + */ + public function actionNotfound() + { + e107::getError()->render(404); + } + +} diff --git a/e107_core/controllers/system/index.php b/e107_core/controllers/system/index.php index 9234c4b62..287668e58 100644 --- a/e107_core/controllers/system/index.php +++ b/e107_core/controllers/system/index.php @@ -1,23 +1,23 @@ -_redirect('/', false, 301); - } -} +_redirect('/', false, 301); + } +} diff --git a/e107_core/controllers/system/xup.php b/e107_core/controllers/system/xup.php index c4183cbf0..9700a781f 100644 --- a/e107_core/controllers/system/xup.php +++ b/e107_core/controllers/system/xup.php @@ -1,164 +1,164 @@ -backUrl = vartrue($_GET['back']) ? base64_decode($_GET['back']) : true; - } - - public function actionSignup() - { - $allow = true; - $session = e107::getSession(); - if($session->get('HAuthError')) - { - $allow = false; - $session->set('HAuthError', null); - } - - if($allow && vartrue($_GET['provider'])) - { - require_once(e_HANDLER."user_handler.php"); - $provider = new e_user_provider($_GET['provider']); - try - { - $provider->signup($this->backUrl, true, false); // redirect to test page is expected, if true - redirect to SITEURL - } - catch (Exception $e) - { - e107::getMessage()->addError('['.$e->getCode().']'.$e->getMessage(), 'default', true); - } - } - - e107::getRedirect()->redirect(true === $this->backUrl ? SITEURL : $this->backUrl); - } - - public function actionLogin() - { - $allow = true; - $session = e107::getSession(); - if($session->get('HAuthError')) - { - $allow = false; - $session->set('HAuthError', null); - } - - if($allow && vartrue($_GET['provider'])) - { - require_once(e_HANDLER."user_handler.php"); - $provider = new e_user_provider($_GET['provider']); - try - { - $provider->login($this->backUrl); // redirect to test page is expected, if true - redirect to SITEURL - } - catch (Exception $e) - { - e107::getMessage()->addError('['.$e->getCode().']'.$e->getMessage(), 'default', true); - } - } - e107::getRedirect()->redirect(true === $this->backUrl ? SITEURL : $this->backUrl); - } - - public function actionTest() - { - echo '

'.LAN_XUP_ERRM_07.'

'; - - if(getperms('0')) - { - echo e107::getMessage()->addError(LAN_XUP_ERRM_08)->render(); - return; - } - - if(isset($_GET['lgt'])) - { - e107::getUser()->logout(); - } - - $profileData = null; - $provider = e107::getUser()->getProvider(); - if($provider) - { - $profileData = $provider->getUserProfile(); - - if(!empty($profileData)) - { - print_a($profileData); - } - - - } - - echo ' '.LAN_XUP_ERRM_11.' '.(e107::getUser()->isUser() && !empty($profileData) ? 'true' : 'false'); - - - $testUrl = SITEURL."?route=system/xup/test"; - $providers = e107::getPref('social_login', array()); - - foreach($providers as $key=>$var) - { - if($var['enabled'] == 1) - { - echo '

'.$key.'

"; - } - - // print_a($var); - } - - echo '

'.LAN_XUP_ERRM_12.''; - - /* - echo '

Facebook

'; - echo '
Test login with Facebook'; - echo '
Test signup with Facebook'; - - echo '

Twitter

'; - echo '
Test login with Twitter'; - echo '
Test signup with Twitter'; - - */ - } - - public function actionEndpoint() - { - require_once( e_HANDLER."hybridauth/Hybrid/Auth.php" ); - require_once( e_HANDLER."hybridauth/Hybrid/Endpoint.php" ); - require_once( e_HANDLER."hybridauth/vendor/autoload.php"); - - try - { - Hybrid_Endpoint::process(); - } - catch (Exception $e) - { - e107::getMessage()->addError('['.$e->getCode().']'.$e->getMessage(), 'default', true); - $session = e107::getSession(); - $session->set('HAuthError', true); - } - } -} +backUrl = vartrue($_GET['back']) ? base64_decode($_GET['back']) : true; + } + + public function actionSignup() + { + $allow = true; + $session = e107::getSession(); + if($session->get('HAuthError')) + { + $allow = false; + $session->set('HAuthError', null); + } + + if($allow && vartrue($_GET['provider'])) + { + require_once(e_HANDLER."user_handler.php"); + $provider = new e_user_provider($_GET['provider']); + try + { + $provider->signup($this->backUrl, true, false); // redirect to test page is expected, if true - redirect to SITEURL + } + catch (Exception $e) + { + e107::getMessage()->addError('['.$e->getCode().']'.$e->getMessage(), 'default', true); + } + } + + e107::getRedirect()->redirect(true === $this->backUrl ? SITEURL : $this->backUrl); + } + + public function actionLogin() + { + $allow = true; + $session = e107::getSession(); + if($session->get('HAuthError')) + { + $allow = false; + $session->set('HAuthError', null); + } + + if($allow && vartrue($_GET['provider'])) + { + require_once(e_HANDLER."user_handler.php"); + $provider = new e_user_provider($_GET['provider']); + try + { + $provider->login($this->backUrl); // redirect to test page is expected, if true - redirect to SITEURL + } + catch (Exception $e) + { + e107::getMessage()->addError('['.$e->getCode().']'.$e->getMessage(), 'default', true); + } + } + e107::getRedirect()->redirect(true === $this->backUrl ? SITEURL : $this->backUrl); + } + + public function actionTest() + { + echo '

'.LAN_XUP_ERRM_07.'

'; + + if(getperms('0')) + { + echo e107::getMessage()->addError(LAN_XUP_ERRM_08)->render(); + return; + } + + if(isset($_GET['lgt'])) + { + e107::getUser()->logout(); + } + + $profileData = null; + $provider = e107::getUser()->getProvider(); + if($provider) + { + $profileData = $provider->getUserProfile(); + + if(!empty($profileData)) + { + print_a($profileData); + } + + + } + + echo ' '.LAN_XUP_ERRM_11.' '.(e107::getUser()->isUser() && !empty($profileData) ? 'true' : 'false'); + + + $testUrl = SITEURL."?route=system/xup/test"; + $providers = e107::getPref('social_login', array()); + + foreach($providers as $key=>$var) + { + if($var['enabled'] == 1) + { + echo '

'.$key.'

"; + } + + // print_a($var); + } + + echo '

'.LAN_XUP_ERRM_12.''; + + /* + echo '

Facebook

'; + echo '
Test login with Facebook'; + echo '
Test signup with Facebook'; + + echo '

Twitter

'; + echo '
Test login with Twitter'; + echo '
Test signup with Twitter'; + + */ + } + + public function actionEndpoint() + { + require_once( e_HANDLER."hybridauth/Hybrid/Auth.php" ); + require_once( e_HANDLER."hybridauth/Hybrid/Endpoint.php" ); + require_once( e_HANDLER."hybridauth/vendor/autoload.php"); + + try + { + Hybrid_Endpoint::process(); + } + catch (Exception $e) + { + e107::getMessage()->addError('['.$e->getCode().']'.$e->getMessage(), 'default', true); + $session = e107::getSession(); + $session->set('HAuthError', true); + } + } +} diff --git a/e107_core/shortcodes/single/sitecontactinfo.sc b/e107_core/shortcodes/single/sitecontactinfo.sc index a7cb0d509..b6bdd6748 100644 --- a/e107_core/shortcodes/single/sitecontactinfo.sc +++ b/e107_core/shortcodes/single/sitecontactinfo.sc @@ -1,2 +1,2 @@ -// text pair. - * - * The text is displayed in a drop-down; the value is returned. - * - * If function timezones_value() exists, it is called to create the displayed - * text. - */ - - -/** - * Class extended_timezones. - */ -class extended_timezones -{ - - /** - * @var array - */ - private $timezonesList = array(); - - /** - * @var bool - */ - private $isEOF = false; // True if at last element of list. - - /** - * @var bool - */ - private $bufferValid = false; - - /** - * Constructor. - */ - public function __construct() - { - $this->timezonesList = systemTimeZones(); - } - - /** - * Call before using the 'next' format option, to ensure the array is - * indexed from the beginning. - */ - public function pointerReset() - { - $this->isEOF = (false === reset($this->timezonesList)); - $this->bufferValid = true; - } - - - /** - * Return a formatted timezone value - * - * @param mixed $key - * The key value to select. - * @param string $formatSpec - * Defines format of return value. - * - * @return mixed - * (according to $formatSpec). - * false - if no value available. - * 'array' - a single-element array; key as passed, and value to match key - * 'next' - as 'array', but ignores the passed $key and moves to next value. - * 'default' - a string usable for display. - */ - public function getValue($key, $formatSpec = '') - { - if($formatSpec == 'next') - { - // Make sure buffer is defined. - if(!$this->bufferValid) - { - $this->pointerReset(); - } - - if($this->isEOF) - { - return false; - } - - $key = key($this->timezonesList); - $val = current($this->timezonesList); - - if(false === $val) - { - $this->isEOF = true; - return false; - } - - $this->isEOF = (false === next($this->timezonesList)); - - return array($key => $val); - } - - $exists = isset($this->timezonesList[$key]); - - if(!$exists) - { - return false; - } - - $val = $this->timezonesList[$key]; - - if($formatSpec == 'array') - { - return array($key => $val); - } - - // Default (as per earlier implementations) - can be specified with - // 'display' format. - return $val; - } -} + text pair. + * + * The text is displayed in a drop-down; the value is returned. + * + * If function timezones_value() exists, it is called to create the displayed + * text. + */ + + +/** + * Class extended_timezones. + */ +class extended_timezones +{ + + /** + * @var array + */ + private $timezonesList = array(); + + /** + * @var bool + */ + private $isEOF = false; // True if at last element of list. + + /** + * @var bool + */ + private $bufferValid = false; + + /** + * Constructor. + */ + public function __construct() + { + $this->timezonesList = systemTimeZones(); + } + + /** + * Call before using the 'next' format option, to ensure the array is + * indexed from the beginning. + */ + public function pointerReset() + { + $this->isEOF = (false === reset($this->timezonesList)); + $this->bufferValid = true; + } + + + /** + * Return a formatted timezone value + * + * @param mixed $key + * The key value to select. + * @param string $formatSpec + * Defines format of return value. + * + * @return mixed + * (according to $formatSpec). + * false - if no value available. + * 'array' - a single-element array; key as passed, and value to match key + * 'next' - as 'array', but ignores the passed $key and moves to next value. + * 'default' - a string usable for display. + */ + public function getValue($key, $formatSpec = '') + { + if($formatSpec == 'next') + { + // Make sure buffer is defined. + if(!$this->bufferValid) + { + $this->pointerReset(); + } + + if($this->isEOF) + { + return false; + } + + $key = key($this->timezonesList); + $val = current($this->timezonesList); + + if(false === $val) + { + $this->isEOF = true; + return false; + } + + $this->isEOF = (false === next($this->timezonesList)); + + return array($key => $val); + } + + $exists = isset($this->timezonesList[$key]); + + if(!$exists) + { + return false; + } + + $val = $this->timezonesList[$key]; + + if($formatSpec == 'array') + { + return array($key => $val); + } + + // Default (as per earlier implementations) - can be specified with + // 'display' format. + return $val; + } +} diff --git a/e107_core/url/news/sef_full_url.php b/e107_core/url/news/sef_full_url.php index 3958d118d..85b7d5c0a 100644 --- a/e107_core/url/news/sef_full_url.php +++ b/e107_core/url/news/sef_full_url.php @@ -1,133 +1,133 @@ - array( - 'allowMain' => true, - 'legacy' => '{e_BASE}news.php', - 'format' => 'path', - 'defaultRoute' => 'list/items', - 'urlSuffix' => '', - 'allowVars' => false, - 'matchValue' => 'empty', - - 'mapVars' => array( - 'news_id' => 'id', - 'news_sef' => 'name', - ), - ), - - 'rules' => array( - '/' => array('list/items', 'allowVars' => array('page'), 'legacyQuery' => 'default.0.{page}', ), - 'Category' => array('list/items', 'allowVars' => array('page'), 'legacyQuery' => 'default.0.{page}', ), - 'Category/' => array('list/category', 'allowVars' => array('page'), 'mapVars' => array('category_sef' => 'name'), 'legacyQuery' => 'list.{name}.{page}', 'parseCallback' => 'categoryIdByTitle'), - 'All' => array('list/all', 'allowVars' => array('page'), 'legacyQuery' => 'all.0.{page}'), - - 'Short/' => array('list/short', 'allowVars' => array('page'), 'mapVars' => array('category_sef' => 'name'), 'legacyQuery' => 'cat.{name}.{page}', 'parseCallback' => 'categoryIdByTitle'), - 'Short/' => array('list/short', 'allowVars' => array('page'), 'mapVars' => array('category_id' => 'id'), 'legacyQuery' => 'cat.{id}.{page}'), - 'Day/' => array('list/day', 'allowVars' => array('page'), 'legacyQuery' => 'day.{id}.{page}'), - 'Month/' => array('list/month', 'allowVars' => array('page'), 'legacyQuery' => 'month.{id}.{page}'), - 'Tag/' => array('list/tag', 'allowVars' => array('page'), 'legacyQuery' => 'tag={tag}&page={page}'), - 'Author/' => array('list/author', 'allowVars' => array('page'), 'legacyQuery' => 'author={author}&page={$page}'), - - '/' => array('view/item', 'mapVars' => array('category_sef' => 'category', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'), - '' => array('view/item', 'mapVars' => array('news_id' => 'id', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'), - '' => array('view/item', 'mapVars' => array('news_id' => 'id'), 'legacyQuery' => 'extend.{id}'), - - ) - ); - - } - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - - 'labels' => array( - 'name' => LAN_EURL_CORE_NEWS, // Module name - 'label' => LAN_EURL_NEWS_REWRITEF_LABEL, // Current profile name - 'description' => LAN_EURL_NEWS_REWRITEF_DESCR, // - 'examples' => array("{SITEURL}news/news-category/news-title","{SITEURL}news/category/news-category") - ), - 'generate' => array('table'=> 'news', 'primary'=>'news_id', 'input'=>'news_title', 'output'=>'news_sef'), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } - - ### CUSTOM METHODS ### - - /** - * view/item by name callback - * @param eRequest $request - */ - public function itemIdByTitle(eRequest $request) - { - $name = $request->getRequestParam('name'); - if(($id = $request->getRequestParam('id'))) - { - $request->setRequestParam('name', $id); - return; - } - elseif(!$name) return; - elseif(is_numeric($name)) - { - return; - } - - $sql = e107::getDb('url'); - $name = e107::getParser()->toDB($name); - if($sql->select('news', 'news_id', "news_sef='{$name}'")) // TODO - it'll be news_sef (new) field - { - $name = $sql->fetch(); - $request->setRequestParam('name', $name['news_id']); - } - else $request->setRequestParam('name', 0); - } - - /** - * list/items by name callback - * @param eRequest $request - */ - public function categoryIdByTitle(eRequest $request) - { - $name = $request->getRequestParam('name'); - if(($id = $request->getRequestParam('id'))) - { - $request->setRequestParam('name', $id); - return; - } - elseif(!$name) return; - elseif(is_numeric($name)) - { - return; - } - - $sql = e107::getDb('url'); - $id = e107::getParser()->toDB($name); - if($sql->select('news_category', 'category_id', "category_sef='{$name}'")) // TODO - it'll be category_sef (new) field - { - $name = $sql->fetch(); - $request->setRequestParam('name', $name['category_id']); - } - else $request->setRequestParam('name', 0); - } -} + array( + 'allowMain' => true, + 'legacy' => '{e_BASE}news.php', + 'format' => 'path', + 'defaultRoute' => 'list/items', + 'urlSuffix' => '', + 'allowVars' => false, + 'matchValue' => 'empty', + + 'mapVars' => array( + 'news_id' => 'id', + 'news_sef' => 'name', + ), + ), + + 'rules' => array( + '/' => array('list/items', 'allowVars' => array('page'), 'legacyQuery' => 'default.0.{page}', ), + 'Category' => array('list/items', 'allowVars' => array('page'), 'legacyQuery' => 'default.0.{page}', ), + 'Category/' => array('list/category', 'allowVars' => array('page'), 'mapVars' => array('category_sef' => 'name'), 'legacyQuery' => 'list.{name}.{page}', 'parseCallback' => 'categoryIdByTitle'), + 'All' => array('list/all', 'allowVars' => array('page'), 'legacyQuery' => 'all.0.{page}'), + + 'Short/' => array('list/short', 'allowVars' => array('page'), 'mapVars' => array('category_sef' => 'name'), 'legacyQuery' => 'cat.{name}.{page}', 'parseCallback' => 'categoryIdByTitle'), + 'Short/' => array('list/short', 'allowVars' => array('page'), 'mapVars' => array('category_id' => 'id'), 'legacyQuery' => 'cat.{id}.{page}'), + 'Day/' => array('list/day', 'allowVars' => array('page'), 'legacyQuery' => 'day.{id}.{page}'), + 'Month/' => array('list/month', 'allowVars' => array('page'), 'legacyQuery' => 'month.{id}.{page}'), + 'Tag/' => array('list/tag', 'allowVars' => array('page'), 'legacyQuery' => 'tag={tag}&page={page}'), + 'Author/' => array('list/author', 'allowVars' => array('page'), 'legacyQuery' => 'author={author}&page={$page}'), + + '/' => array('view/item', 'mapVars' => array('category_sef' => 'category', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'), + '' => array('view/item', 'mapVars' => array('news_id' => 'id', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'), + '' => array('view/item', 'mapVars' => array('news_id' => 'id'), 'legacyQuery' => 'extend.{id}'), + + ) + ); + + } + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + + 'labels' => array( + 'name' => LAN_EURL_CORE_NEWS, // Module name + 'label' => LAN_EURL_NEWS_REWRITEF_LABEL, // Current profile name + 'description' => LAN_EURL_NEWS_REWRITEF_DESCR, // + 'examples' => array("{SITEURL}news/news-category/news-title","{SITEURL}news/category/news-category") + ), + 'generate' => array('table'=> 'news', 'primary'=>'news_id', 'input'=>'news_title', 'output'=>'news_sef'), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } + + ### CUSTOM METHODS ### + + /** + * view/item by name callback + * @param eRequest $request + */ + public function itemIdByTitle(eRequest $request) + { + $name = $request->getRequestParam('name'); + if(($id = $request->getRequestParam('id'))) + { + $request->setRequestParam('name', $id); + return; + } + elseif(!$name) return; + elseif(is_numeric($name)) + { + return; + } + + $sql = e107::getDb('url'); + $name = e107::getParser()->toDB($name); + if($sql->select('news', 'news_id', "news_sef='{$name}'")) // TODO - it'll be news_sef (new) field + { + $name = $sql->fetch(); + $request->setRequestParam('name', $name['news_id']); + } + else $request->setRequestParam('name', 0); + } + + /** + * list/items by name callback + * @param eRequest $request + */ + public function categoryIdByTitle(eRequest $request) + { + $name = $request->getRequestParam('name'); + if(($id = $request->getRequestParam('id'))) + { + $request->setRequestParam('name', $id); + return; + } + elseif(!$name) return; + elseif(is_numeric($name)) + { + return; + } + + $sql = e107::getDb('url'); + $id = e107::getParser()->toDB($name); + if($sql->select('news_category', 'category_id', "category_sef='{$name}'")) // TODO - it'll be category_sef (new) field + { + $name = $sql->fetch(); + $request->setRequestParam('name', $name['category_id']); + } + else $request->setRequestParam('name', 0); + } +} diff --git a/e107_core/url/news/sef_noid_url.php b/e107_core/url/news/sef_noid_url.php index 5ce292cd6..687e69f24 100644 --- a/e107_core/url/news/sef_noid_url.php +++ b/e107_core/url/news/sef_noid_url.php @@ -1,327 +1,327 @@ - array( - 'allowMain' => true, - 'noSingleEntry' => false, // [optional] default false; disallow this module to be shown via single entry point when this config is used - 'legacy' => '{e_BASE}news.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script - 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'selfParse' => true, // [optional] default false; use only this->parse() method, no core routine URL parsing - 'selfCreate' => true, // [optional] default false; use only this->create() method, no core routine URL creating - 'defaultRoute' => 'list/items', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - 'urlSuffix' => '.html', // [optional] default empty; string to append to the URL (e.g. .html) - ), - ); - } - - /** - * When returning array, module or it's corresponding alias will be prefixed - * Create link so that it can be mapped by the parse() method - * - view/item?id=xxx -> news/xxx - * - list/items[?page=xxx] -> news[?page=xxx] - * - list/category?id=xxx[&page=xxx] -> news/Category/xxx?page=xxx - * - list/category?id=0[&page=xxx] -> news?page=xxx - * - list/short?id=xxx[&page=xxx] -> news/Short/xxx?page=xxx - * - list/category?id=xxx[&page=xxx] -> news?page=xxx - * - list/day?id=xxx -> news/Day-id - * - list/month?id=xxx -> news/Month-id - * - list/year?id=xxx -> news/Year-id - * - list/nextprev?route=xxx -> PARSED_ROUTE?page=[FROM] (recursive parse() call) - * - list/all - * - list/tag - */ - public function create($route, $params = array(), $options = array()) - { - - if('--FROM--' != vartrue($params['page'])) $page = varset($params['page']) ? intval($params['page']) : '0'; - else $page = '--FROM--'; - - if(!$route) $route = 'list/items'; - if(is_string($route)) $route = explode('/', $route, 2); - if('index' == $route[0]) - { - $route[0] = 'list'; - $route[1] = 'items'; - } - elseif('index' == $route[1]) - { - $route[1] = 'items'; - } - - $r = array(); - $parm = array(); - - if($route[0] == 'view') - { - ## news are passing array as it is retrieved from the DB, map vars to proper values - if(isset($params['news_id']) && !empty($params['news_id'])) $params['id'] = $params['news_id']; - if(isset($params['news_sef']) && !empty($params['news_sef'])) $params['id'] = $params['news_sef']; // TODO - news_sef - - switch ($route[1]) - { - case 'item': - $r[0] = $params['id']; // news/ID - break; - - default: - - break; - } - } - elseif($route[0] == 'list') - { - ## news are passing array as it is retrieved from the DB, map vars to proper values - if(isset($params['category_id']) && !empty($params['category_id'])) $params['id'] = $params['category_id']; - if(isset($params['category_sef']) && !empty($params['category_sef'])) $params['name'] = $params['category_sef']; // TODO - news_sef - - switch ($route[1]) - { - - case 'items': - $r[0] = ''; - if($page) $parm = array('page' => $page); // news?page=xxx - break; - - case 'all': - $r[0] = 'All'; - if($page) $parm = array('page' => $page); // news/All?page=xxx - break; - - case 'tag': // news/tag/xxxx - $r[0] = 'tag'; - $r[1] = $params['tag']; - if($page) $parm = array('page' => $page); - break; - - case 'author': // news/author/xxxx - $r[0] = 'author'; - $r[1] = $params['author']; - if($page) $parm = array('page' => $page); - break; - - case 'category': - case 'short': - if(!vartrue($params['id'])) - { - $r[0] = ''; - if($page) $parm = array('page' => $page); // news?page=xxx - } - else - { - // news/Category/Category-Name?page=xxx - // news/Short/Category-Name?page=xxx - $r[0] = $route[1] == 'category' ? 'Category' : 'Short'; - $r[1] = !empty($params['name']) ? $params['name'] : $params['id']; - if($page) $parm = array('page' => $page); - } - break; - - case 'day': - case 'month': - case 'year': - $r = array($route[1], intval($params['id'])); - if($page) $parm = array('page' => $page); - break; - - default: - - break; - } - } - - if(empty($r)) return false; - - - //XXX TODO Find a better place to put this check. - $urlFormat = e107::getConfig()->get('url_sef_translate'); - if($urlFormat == 'dashl' || $urlFormat == 'underscorel' || $urlFormat == 'plusl') // convert template to lowercase when using lowercase SEF URL format. - { - $r[0] = strtolower($r[0]); - } - - - return array($r, $parm); - } - - /** - * Manually parse request - * Pathinfo DOESN'T contain leading 'module' (e.g news or alias 'Blog') - * Retruned route shouldn't contain module as well, unless you manipulate $request directly and set $request->routed to true - * Mapped URLs: - * - news/News-Item -> extend.xxx - * - news/Category/Category-Name?page=10 -> list.xxx.10 - * - news/Day|Month-xxx -> day|month-xxx - */ - public function parse($pathInfo, $params = array(), eRequest $request = null, eRouter $router = null, $config = array()) - { - - $page = !empty($params['page']) ? intval($params['page']) : '0'; - if(!$pathInfo) - { - ## this var is used by default from legacy() method - ## you may override legacy() method - ## Keep in mind legacy() is not triggered at all if parse() returns false or $request->routed is set to true - $this->legacyQueryString = $page ? 'default.0.'.$page : ''; - return $config['defaultRoute']; - } - - ## no controller/action pair - news item view - map to extend.xxx - if(strpos($pathInfo, '/') === false && strtolower($pathInfo) != 'all') - { - - $route = 'view/item'; - $id = is_numeric($pathInfo) ? intval($pathInfo) : $this->itemIdByTitle($pathInfo); - if(!$id) - { - ## let news.php handle missing news item - $this->legacyQueryString = 'extend.0'; - return $route; - } - $this->legacyQueryString = 'extend.'.$id; - return $route; - } - - $parts = explode('/', $pathInfo, 2); - $parts[0] = strtolower($parts[0]); - switch ($parts[0]) - { - # map to list.xxx.xxx - case 'short': - case 'category': - # Hardcoded leading string for categories, could be pref or LAN constant - if(!vartrue($parts[1])) - { - ## force not found as we don't want to have duplicated content (default.0.xxx) - return false; - } - else - { - if(!is_numeric($parts[1])) $id = $this->categoryIdByTitle($parts[1]); - else $id = intval($parts[1]); - } - if(!$id) - { - # let news.php handle it - $id = 0; - } - $action = $parts[0] == 'short' ? 'cat' : 'list'; - $this->legacyQueryString = $action.'.'.$id.'.'.$page; - return 'item/list'; - break; - - # could be pref or LAN constant - case 'day': - if(!vartrue($parts[1])) $id = 0; - else $id = intval($parts[1]); - - $this->legacyQueryString = 'day.'.$id.'.'.$page; - return 'list/day'; - break; - - # could be pref or LAN constant - case 'month': - if(!vartrue($parts[1])) $id = 0; - else $id = intval($parts[1]); - - $this->legacyQueryString = 'month.'.$id.'.'.$page; - return 'list/month'; - break; - - # could be pref or LAN constant - not supported yet - case 'year': - if(!vartrue($parts[1])) $id = 0; - else $id = intval($parts[1]); - - $this->legacyQueryString = 'year.'.$id.'.'.$page; - //return 'list/year'; - break; - - case 'all': - $this->legacyQueryString = 'all.0.'.$page; - return 'list/all'; - break; - - case 'tag': // url: news/tag/xxxxx - $this->legacyQueryString = 'tag='.$parts[1]; - return 'list/tag'; - break; - - case 'author': // url: news/author/xxxxx - $this->legacyQueryString = 'author='.$parts[1].'&page='.$page; - return 'list/author'; - break; - - # force not found - default: - return false; - break; - } - - return false; - } - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - 'labels' => array( - 'name' => LAN_EURL_CORE_NEWS, // Module name - 'label' => LAN_EURL_NEWS_REWRITE_LABEL, // Current profile name - 'description' => LAN_EURL_NEWS_REWRITE_DESCR, // - 'examples' => array("{SITEURL}news/news-title") - ), - 'generate' => array('table'=> 'news', 'primary'=>'news_id', 'input'=>'news_title', 'output'=>'news_sef'), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } - - ### CUSTOM METHODS ### - - //retrieve news_id by news_sef ( - public function itemIdByTitle($id) - { - $sql = e107::getDb('url'); - $tp = e107::getParser(); - $id = $tp->toDB($id); - if($sql->select('news', 'news_id', "news_sef='{$id}'")) - { - $id = $sql->fetch(); - return $id['news_id']; - } - return false; - } - - //retrieve category_id by Title (XXX - category_sef column, equals to category_sef if not set explicit) - public function categoryIdByTitle($id) - { - $sql = e107::getDb('url'); - $tp = e107::getParser(); - $id = $tp->toDB($id); - if($sql->select('news_category', 'category_id', "category_sef='{$id}'")) - { - $id = $sql->fetch(); - return $id['category_id']; - } - return false; - } -} + array( + 'allowMain' => true, + 'noSingleEntry' => false, // [optional] default false; disallow this module to be shown via single entry point when this config is used + 'legacy' => '{e_BASE}news.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script + 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored + 'selfParse' => true, // [optional] default false; use only this->parse() method, no core routine URL parsing + 'selfCreate' => true, // [optional] default false; use only this->create() method, no core routine URL creating + 'defaultRoute' => 'list/items', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ + 'urlSuffix' => '.html', // [optional] default empty; string to append to the URL (e.g. .html) + ), + ); + } + + /** + * When returning array, module or it's corresponding alias will be prefixed + * Create link so that it can be mapped by the parse() method + * - view/item?id=xxx -> news/xxx + * - list/items[?page=xxx] -> news[?page=xxx] + * - list/category?id=xxx[&page=xxx] -> news/Category/xxx?page=xxx + * - list/category?id=0[&page=xxx] -> news?page=xxx + * - list/short?id=xxx[&page=xxx] -> news/Short/xxx?page=xxx + * - list/category?id=xxx[&page=xxx] -> news?page=xxx + * - list/day?id=xxx -> news/Day-id + * - list/month?id=xxx -> news/Month-id + * - list/year?id=xxx -> news/Year-id + * - list/nextprev?route=xxx -> PARSED_ROUTE?page=[FROM] (recursive parse() call) + * - list/all + * - list/tag + */ + public function create($route, $params = array(), $options = array()) + { + + if('--FROM--' != vartrue($params['page'])) $page = varset($params['page']) ? intval($params['page']) : '0'; + else $page = '--FROM--'; + + if(!$route) $route = 'list/items'; + if(is_string($route)) $route = explode('/', $route, 2); + if('index' == $route[0]) + { + $route[0] = 'list'; + $route[1] = 'items'; + } + elseif('index' == $route[1]) + { + $route[1] = 'items'; + } + + $r = array(); + $parm = array(); + + if($route[0] == 'view') + { + ## news are passing array as it is retrieved from the DB, map vars to proper values + if(isset($params['news_id']) && !empty($params['news_id'])) $params['id'] = $params['news_id']; + if(isset($params['news_sef']) && !empty($params['news_sef'])) $params['id'] = $params['news_sef']; // TODO - news_sef + + switch ($route[1]) + { + case 'item': + $r[0] = $params['id']; // news/ID + break; + + default: + + break; + } + } + elseif($route[0] == 'list') + { + ## news are passing array as it is retrieved from the DB, map vars to proper values + if(isset($params['category_id']) && !empty($params['category_id'])) $params['id'] = $params['category_id']; + if(isset($params['category_sef']) && !empty($params['category_sef'])) $params['name'] = $params['category_sef']; // TODO - news_sef + + switch ($route[1]) + { + + case 'items': + $r[0] = ''; + if($page) $parm = array('page' => $page); // news?page=xxx + break; + + case 'all': + $r[0] = 'All'; + if($page) $parm = array('page' => $page); // news/All?page=xxx + break; + + case 'tag': // news/tag/xxxx + $r[0] = 'tag'; + $r[1] = $params['tag']; + if($page) $parm = array('page' => $page); + break; + + case 'author': // news/author/xxxx + $r[0] = 'author'; + $r[1] = $params['author']; + if($page) $parm = array('page' => $page); + break; + + case 'category': + case 'short': + if(!vartrue($params['id'])) + { + $r[0] = ''; + if($page) $parm = array('page' => $page); // news?page=xxx + } + else + { + // news/Category/Category-Name?page=xxx + // news/Short/Category-Name?page=xxx + $r[0] = $route[1] == 'category' ? 'Category' : 'Short'; + $r[1] = !empty($params['name']) ? $params['name'] : $params['id']; + if($page) $parm = array('page' => $page); + } + break; + + case 'day': + case 'month': + case 'year': + $r = array($route[1], intval($params['id'])); + if($page) $parm = array('page' => $page); + break; + + default: + + break; + } + } + + if(empty($r)) return false; + + + //XXX TODO Find a better place to put this check. + $urlFormat = e107::getConfig()->get('url_sef_translate'); + if($urlFormat == 'dashl' || $urlFormat == 'underscorel' || $urlFormat == 'plusl') // convert template to lowercase when using lowercase SEF URL format. + { + $r[0] = strtolower($r[0]); + } + + + return array($r, $parm); + } + + /** + * Manually parse request + * Pathinfo DOESN'T contain leading 'module' (e.g news or alias 'Blog') + * Retruned route shouldn't contain module as well, unless you manipulate $request directly and set $request->routed to true + * Mapped URLs: + * - news/News-Item -> extend.xxx + * - news/Category/Category-Name?page=10 -> list.xxx.10 + * - news/Day|Month-xxx -> day|month-xxx + */ + public function parse($pathInfo, $params = array(), eRequest $request = null, eRouter $router = null, $config = array()) + { + + $page = !empty($params['page']) ? intval($params['page']) : '0'; + if(!$pathInfo) + { + ## this var is used by default from legacy() method + ## you may override legacy() method + ## Keep in mind legacy() is not triggered at all if parse() returns false or $request->routed is set to true + $this->legacyQueryString = $page ? 'default.0.'.$page : ''; + return $config['defaultRoute']; + } + + ## no controller/action pair - news item view - map to extend.xxx + if(strpos($pathInfo, '/') === false && strtolower($pathInfo) != 'all') + { + + $route = 'view/item'; + $id = is_numeric($pathInfo) ? intval($pathInfo) : $this->itemIdByTitle($pathInfo); + if(!$id) + { + ## let news.php handle missing news item + $this->legacyQueryString = 'extend.0'; + return $route; + } + $this->legacyQueryString = 'extend.'.$id; + return $route; + } + + $parts = explode('/', $pathInfo, 2); + $parts[0] = strtolower($parts[0]); + switch ($parts[0]) + { + # map to list.xxx.xxx + case 'short': + case 'category': + # Hardcoded leading string for categories, could be pref or LAN constant + if(!vartrue($parts[1])) + { + ## force not found as we don't want to have duplicated content (default.0.xxx) + return false; + } + else + { + if(!is_numeric($parts[1])) $id = $this->categoryIdByTitle($parts[1]); + else $id = intval($parts[1]); + } + if(!$id) + { + # let news.php handle it + $id = 0; + } + $action = $parts[0] == 'short' ? 'cat' : 'list'; + $this->legacyQueryString = $action.'.'.$id.'.'.$page; + return 'item/list'; + break; + + # could be pref or LAN constant + case 'day': + if(!vartrue($parts[1])) $id = 0; + else $id = intval($parts[1]); + + $this->legacyQueryString = 'day.'.$id.'.'.$page; + return 'list/day'; + break; + + # could be pref or LAN constant + case 'month': + if(!vartrue($parts[1])) $id = 0; + else $id = intval($parts[1]); + + $this->legacyQueryString = 'month.'.$id.'.'.$page; + return 'list/month'; + break; + + # could be pref or LAN constant - not supported yet + case 'year': + if(!vartrue($parts[1])) $id = 0; + else $id = intval($parts[1]); + + $this->legacyQueryString = 'year.'.$id.'.'.$page; + //return 'list/year'; + break; + + case 'all': + $this->legacyQueryString = 'all.0.'.$page; + return 'list/all'; + break; + + case 'tag': // url: news/tag/xxxxx + $this->legacyQueryString = 'tag='.$parts[1]; + return 'list/tag'; + break; + + case 'author': // url: news/author/xxxxx + $this->legacyQueryString = 'author='.$parts[1].'&page='.$page; + return 'list/author'; + break; + + # force not found + default: + return false; + break; + } + + return false; + } + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + 'labels' => array( + 'name' => LAN_EURL_CORE_NEWS, // Module name + 'label' => LAN_EURL_NEWS_REWRITE_LABEL, // Current profile name + 'description' => LAN_EURL_NEWS_REWRITE_DESCR, // + 'examples' => array("{SITEURL}news/news-title") + ), + 'generate' => array('table'=> 'news', 'primary'=>'news_id', 'input'=>'news_title', 'output'=>'news_sef'), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } + + ### CUSTOM METHODS ### + + //retrieve news_id by news_sef ( + public function itemIdByTitle($id) + { + $sql = e107::getDb('url'); + $tp = e107::getParser(); + $id = $tp->toDB($id); + if($sql->select('news', 'news_id', "news_sef='{$id}'")) + { + $id = $sql->fetch(); + return $id['news_id']; + } + return false; + } + + //retrieve category_id by Title (XXX - category_sef column, equals to category_sef if not set explicit) + public function categoryIdByTitle($id) + { + $sql = e107::getDb('url'); + $tp = e107::getParser(); + $id = $tp->toDB($id); + if($sql->select('news_category', 'category_id', "category_sef='{$id}'")) + { + $id = $sql->fetch(); + return $id['category_id']; + } + return false; + } +} diff --git a/e107_core/url/news/sef_url.php b/e107_core/url/news/sef_url.php index 00fb395b2..544db9e46 100644 --- a/e107_core/url/news/sef_url.php +++ b/e107_core/url/news/sef_url.php @@ -1,210 +1,210 @@ - array( - 'legacy' => '{e_BASE}news.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script; override per rule is allowed - 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'defaultRoute' => 'list/items', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - 'urlSuffix' => '', - 'allowMain' => true, - - ### default vars mapping (create URL), override per rule is allowed - 'mapVars' => array( - 'news_id' => 'id', - 'news_sef' => 'name', - ), - - ### match will only check if parameter is empty to invalidate the assembling vs current rule - 'matchValue' => 'empty', - - ### Numerical array containing allowed vars by default (create URL, used for legacyQuery parsing in parse routine as well), - ### false means - disallow all vars beside those required by the rules - ### Override per rule is allowed - 'allowVars' => false, - - ### Best news - you don't need to write one and the same - ### regex over and over again. Even better news - you might avoid - ### writing regex at all! Just use the core regex templates, they - ### should fit almost every case. - ### Here is a test custom regex template: - 'varTemplates' => array('testIt' => '[\d]+'), - - /* Predefined Core regex templates, see usage below - 'az' => '[A-Za-z]+', // NOTE - it won't match non-latin word characters! - 'alphanum' => '[\w\pL]+', - 'sefsecure' => '[\w\pL.\-\s!,]+', - 'secure' => '[^\/\'"\\<%]+', - 'number' => '[\d]+', - 'username' => '[\w\pL.\-\s!,]+', - 'azOptional' => '[A-Za-z]{0,}', - 'alphanumOptional' => '[\w\pL]{0,}', - 'sefsecureOptional' => '[\w\pL.\-\s!,]{0,}', - 'secureOptional' => '[^\/\'"\\<%]{0,}', - 'numberOptional' => '[\d]{0,}', - 'usernameOptional' => '[\w\pL.\-\s!,]{0,}', - */ - ), - - 'rules' => array( - ### simple matches first - PERFORMANCE - '' => array('list/items', 'allowVars' => array('page'), 'legacyQuery' => 'default.0.{page}', ), - 'Category' => array('list/items', 'allowVars' => array('page'), 'legacyQuery' => 'default.0.{page}', ), - - ## URL with ID and Title - no DB call, balanced performance, name optional - ## Demonstrating the usage of custom user defined regex template defined above - 'testIt' - 'Category//' => array('list/category', 'allowVars' => array('page'), 'mapVars' => array('category_id' => 'id', 'category_sef' => 'name'), 'legacyQuery' => 'list.{id}.{page}'), - - ## URL with Title only - prettiest and slowest! Example with direct regex - no templates - //'Category/' => array('list/category', 'allowVars' => array('page'), 'mapVars' => array('category_sef' => 'name'), 'legacyQuery' => 'list.{name}.{page}', 'parseCallback' => 'categoryIdByTitle'), - - ## URL with ID only - best performance, fallback when no sef name provided - 'Category/' => array('list/category', 'allowVars' => array('page'), 'legacyQuery' => 'list.{id}.{page}', 'mapVars' => array('category_id' => 'id')), - - ### View item requested by id or string, if you remove the catch ALL example, uncomment at least on row from this block - ### leading category name example - could be enabled together with the next example to handle creating of URLs without knowing the category title - // 'View//' => array('view/item', 'mapVars' => array('news_sef' => 'name', 'category_sef' => 'category'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'), - // to be noted here - value 'name' is replaced by item id within the callback method; TODO replace news_sef with news_sef field - // 'View/' => array('view/item', 'mapVars' => array('news_sef' => 'name', 'news_id' => 'id'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'), - // 'View/' => array('view/item', 'mapVars' => array('news_id' => 'id'), 'legacyQuery' => 'extend.{id}'), - - ## All news - 'All' => array('list/all', 'allowVars' => array('page'), 'legacyQuery' => 'all.0.{page}'), - - ## URL with ID and Title - no DB call, balanced performance! - 'Short//' => array('list/short', 'allowVars' => array('page'), 'mapVars' => array('category_id' => 'id', 'category_sef' => 'name'), 'legacyQuery' => 'cat.{id}.{page}'), - ## fallback when name is not provided - 'Short/' => array('list/short', 'allowVars' => array('page'), 'mapVars' => array('category_id' => 'id'), 'legacyQuery' => 'cat.{id}.{page}'), - - // less used after - //'Brief/' => array('list/short', 'allowVars' => array('page'), 'legacyQuery' => 'cat.{id}.{page}', 'mapVars' => array('category_id' => 'id')), - 'Day/' => array('list/day', 'allowVars' => array('page'), 'legacyQuery' => 'day.{id}.{page}'), - 'Month/' => array('list/month', 'allowVars' => array('page'), 'legacyQuery' => 'month.{id}.{page}'), - //'Year/' => array('list/year', 'allowVars' => array('page'), 'legacyQuery' => 'year.{id}.{page}'), not supported yet - - ### View news item - kinda catch all - very bad performance when News is chosen as default namespace - two additional DB queries on every site call! - ## Leading category name - uncomment to enable - //'/' => array('view/item', 'mapVars' => array('category_sef' => 'category', 'news_sef' => 'name', 'news_id' => 'id'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'), - 'View///' => array('view/item', 'mapVars' => array('category_sef' => 'category', 'news_sef' => 'name', 'news_id' => 'id'), 'legacyQuery' => 'extend.{id}'), - // Base location as item view - fallback if category sef is missing - //'' => array('view/item', 'mapVars' => array('news_id' => 'id', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'), - // fallback if news sef is missing - 'View//' => array('view/item', 'mapVars' => array('news_id' => 'id', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{id}'), - - 'View/' => array('view/item', 'mapVars' => array('news_id' => 'id'), 'legacyQuery' => 'extend.{id}'), - - 'Tag/' => array('list/tag', 'allowVars' => array('page'), 'legacyQuery' => 'tag={tag}&page={page}'), - - 'Author/' => array('list/author', 'allowVars' => array('page'), 'legacyQuery' => 'author={author}&page={page}'), - ) - ); - } - - /** - * Query mapping in format route?params: - * - item/view?id=xxx -> ?extend.id - * - list/items[?page=xxx] -> default.0.page - * - list/category?id=xxx[&page=xxx] -> list.id.page - * - list/category?id=0[&page=xxx] -> default.0.page - * - list/short?id=xxx[&page=xxx] -> cat.id.page - * - list/day?id=xxx -> ?day-id - * - list/month?id=xxx -> ?month-id - * - list/year?id=xxx -> ?year-id - * - list/nextprev?route=xxx -> PARSED_ROUTE.[FROM] (recursive parse() call) - */ - - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - 'labels' => array( - 'name' => LAN_EURL_CORE_NEWS, // Module name - 'label' => LAN_EURL_NEWS_REWRITEX_LABEL, // Current profile name - 'description' => LAN_EURL_NEWS_REWRITEX_DESCR, // - 'examples' => array('{SITEURL}news/1/news-title') - ), - 'generate' => array('table'=> 'news', 'primary'=>'news_id', 'input'=>'news_title', 'output'=>'news_sef'), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } - - ### CUSTOM METHODS ### - - /** - * view/item by name callback - * @param eRequest $request - */ - /*public function itemIdByTitle(eRequest $request) - { - $name = $request->getRequestParam('name'); - if(($id = $request->getRequestParam('id'))) - { - $request->setRequestParam('name', $id); - return; - } - elseif(!$name) return; - elseif(is_numeric($name)) - { - return; - } - - $sql = e107::getDb('url'); - $name = e107::getParser()->toDB($name); - if($sql->db_Select('news', 'news_id', "news_sef='{$name}'")) // TODO - it'll be news_sef (new) field - { - $name = $sql->db_Fetch(); - $request->setRequestParam('name', $name['news_id']); - } - else $request->setRequestParam('name', 0); - }*/ - - /** - * list/items by name callback - * @param eRequest $request - */ - /*public function categoryIdByTitle(eRequest $request) - { - $name = $request->getRequestParam('name'); - if(($id = $request->getRequestParam('id'))) - { - $request->setRequestParam('name', $id); - return; - } - elseif(!$name) return; - elseif(is_numeric($name)) - { - return; - } - - $sql = e107::getDb('url'); - $id = e107::getParser()->toDB($name); - if($sql->db_Select('news_category', 'category_id', "category_sef='{$name}'")) // TODO - it'll be category_sef (new) field - { - $name = $sql->db_Fetch(); - $request->setRequestParam('name', $name['category_id']); - } - else $request->setRequestParam('name', 0); - }*/ + array( + 'legacy' => '{e_BASE}news.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script; override per rule is allowed + 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored + 'defaultRoute' => 'list/items', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ + 'urlSuffix' => '', + 'allowMain' => true, + + ### default vars mapping (create URL), override per rule is allowed + 'mapVars' => array( + 'news_id' => 'id', + 'news_sef' => 'name', + ), + + ### match will only check if parameter is empty to invalidate the assembling vs current rule + 'matchValue' => 'empty', + + ### Numerical array containing allowed vars by default (create URL, used for legacyQuery parsing in parse routine as well), + ### false means - disallow all vars beside those required by the rules + ### Override per rule is allowed + 'allowVars' => false, + + ### Best news - you don't need to write one and the same + ### regex over and over again. Even better news - you might avoid + ### writing regex at all! Just use the core regex templates, they + ### should fit almost every case. + ### Here is a test custom regex template: + 'varTemplates' => array('testIt' => '[\d]+'), + + /* Predefined Core regex templates, see usage below + 'az' => '[A-Za-z]+', // NOTE - it won't match non-latin word characters! + 'alphanum' => '[\w\pL]+', + 'sefsecure' => '[\w\pL.\-\s!,]+', + 'secure' => '[^\/\'"\\<%]+', + 'number' => '[\d]+', + 'username' => '[\w\pL.\-\s!,]+', + 'azOptional' => '[A-Za-z]{0,}', + 'alphanumOptional' => '[\w\pL]{0,}', + 'sefsecureOptional' => '[\w\pL.\-\s!,]{0,}', + 'secureOptional' => '[^\/\'"\\<%]{0,}', + 'numberOptional' => '[\d]{0,}', + 'usernameOptional' => '[\w\pL.\-\s!,]{0,}', + */ + ), + + 'rules' => array( + ### simple matches first - PERFORMANCE + '' => array('list/items', 'allowVars' => array('page'), 'legacyQuery' => 'default.0.{page}', ), + 'Category' => array('list/items', 'allowVars' => array('page'), 'legacyQuery' => 'default.0.{page}', ), + + ## URL with ID and Title - no DB call, balanced performance, name optional + ## Demonstrating the usage of custom user defined regex template defined above - 'testIt' + 'Category//' => array('list/category', 'allowVars' => array('page'), 'mapVars' => array('category_id' => 'id', 'category_sef' => 'name'), 'legacyQuery' => 'list.{id}.{page}'), + + ## URL with Title only - prettiest and slowest! Example with direct regex - no templates + //'Category/' => array('list/category', 'allowVars' => array('page'), 'mapVars' => array('category_sef' => 'name'), 'legacyQuery' => 'list.{name}.{page}', 'parseCallback' => 'categoryIdByTitle'), + + ## URL with ID only - best performance, fallback when no sef name provided + 'Category/' => array('list/category', 'allowVars' => array('page'), 'legacyQuery' => 'list.{id}.{page}', 'mapVars' => array('category_id' => 'id')), + + ### View item requested by id or string, if you remove the catch ALL example, uncomment at least on row from this block + ### leading category name example - could be enabled together with the next example to handle creating of URLs without knowing the category title + // 'View//' => array('view/item', 'mapVars' => array('news_sef' => 'name', 'category_sef' => 'category'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'), + // to be noted here - value 'name' is replaced by item id within the callback method; TODO replace news_sef with news_sef field + // 'View/' => array('view/item', 'mapVars' => array('news_sef' => 'name', 'news_id' => 'id'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'), + // 'View/' => array('view/item', 'mapVars' => array('news_id' => 'id'), 'legacyQuery' => 'extend.{id}'), + + ## All news + 'All' => array('list/all', 'allowVars' => array('page'), 'legacyQuery' => 'all.0.{page}'), + + ## URL with ID and Title - no DB call, balanced performance! + 'Short//' => array('list/short', 'allowVars' => array('page'), 'mapVars' => array('category_id' => 'id', 'category_sef' => 'name'), 'legacyQuery' => 'cat.{id}.{page}'), + ## fallback when name is not provided + 'Short/' => array('list/short', 'allowVars' => array('page'), 'mapVars' => array('category_id' => 'id'), 'legacyQuery' => 'cat.{id}.{page}'), + + // less used after + //'Brief/' => array('list/short', 'allowVars' => array('page'), 'legacyQuery' => 'cat.{id}.{page}', 'mapVars' => array('category_id' => 'id')), + 'Day/' => array('list/day', 'allowVars' => array('page'), 'legacyQuery' => 'day.{id}.{page}'), + 'Month/' => array('list/month', 'allowVars' => array('page'), 'legacyQuery' => 'month.{id}.{page}'), + //'Year/' => array('list/year', 'allowVars' => array('page'), 'legacyQuery' => 'year.{id}.{page}'), not supported yet + + ### View news item - kinda catch all - very bad performance when News is chosen as default namespace - two additional DB queries on every site call! + ## Leading category name - uncomment to enable + //'/' => array('view/item', 'mapVars' => array('category_sef' => 'category', 'news_sef' => 'name', 'news_id' => 'id'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'), + 'View///' => array('view/item', 'mapVars' => array('category_sef' => 'category', 'news_sef' => 'name', 'news_id' => 'id'), 'legacyQuery' => 'extend.{id}'), + // Base location as item view - fallback if category sef is missing + //'' => array('view/item', 'mapVars' => array('news_id' => 'id', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{name}', 'parseCallback' => 'itemIdByTitle'), + // fallback if news sef is missing + 'View//' => array('view/item', 'mapVars' => array('news_id' => 'id', 'news_sef' => 'name'), 'legacyQuery' => 'extend.{id}'), + + 'View/' => array('view/item', 'mapVars' => array('news_id' => 'id'), 'legacyQuery' => 'extend.{id}'), + + 'Tag/' => array('list/tag', 'allowVars' => array('page'), 'legacyQuery' => 'tag={tag}&page={page}'), + + 'Author/' => array('list/author', 'allowVars' => array('page'), 'legacyQuery' => 'author={author}&page={page}'), + ) + ); + } + + /** + * Query mapping in format route?params: + * - item/view?id=xxx -> ?extend.id + * - list/items[?page=xxx] -> default.0.page + * - list/category?id=xxx[&page=xxx] -> list.id.page + * - list/category?id=0[&page=xxx] -> default.0.page + * - list/short?id=xxx[&page=xxx] -> cat.id.page + * - list/day?id=xxx -> ?day-id + * - list/month?id=xxx -> ?month-id + * - list/year?id=xxx -> ?year-id + * - list/nextprev?route=xxx -> PARSED_ROUTE.[FROM] (recursive parse() call) + */ + + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + 'labels' => array( + 'name' => LAN_EURL_CORE_NEWS, // Module name + 'label' => LAN_EURL_NEWS_REWRITEX_LABEL, // Current profile name + 'description' => LAN_EURL_NEWS_REWRITEX_DESCR, // + 'examples' => array('{SITEURL}news/1/news-title') + ), + 'generate' => array('table'=> 'news', 'primary'=>'news_id', 'input'=>'news_title', 'output'=>'news_sef'), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } + + ### CUSTOM METHODS ### + + /** + * view/item by name callback + * @param eRequest $request + */ + /*public function itemIdByTitle(eRequest $request) + { + $name = $request->getRequestParam('name'); + if(($id = $request->getRequestParam('id'))) + { + $request->setRequestParam('name', $id); + return; + } + elseif(!$name) return; + elseif(is_numeric($name)) + { + return; + } + + $sql = e107::getDb('url'); + $name = e107::getParser()->toDB($name); + if($sql->db_Select('news', 'news_id', "news_sef='{$name}'")) // TODO - it'll be news_sef (new) field + { + $name = $sql->db_Fetch(); + $request->setRequestParam('name', $name['news_id']); + } + else $request->setRequestParam('name', 0); + }*/ + + /** + * list/items by name callback + * @param eRequest $request + */ + /*public function categoryIdByTitle(eRequest $request) + { + $name = $request->getRequestParam('name'); + if(($id = $request->getRequestParam('id'))) + { + $request->setRequestParam('name', $id); + return; + } + elseif(!$name) return; + elseif(is_numeric($name)) + { + return; + } + + $sql = e107::getDb('url'); + $id = e107::getParser()->toDB($name); + if($sql->db_Select('news_category', 'category_id', "category_sef='{$name}'")) // TODO - it'll be category_sef (new) field + { + $name = $sql->db_Fetch(); + $request->setRequestParam('name', $name['category_id']); + } + else $request->setRequestParam('name', 0); + }*/ } \ No newline at end of file diff --git a/e107_core/url/news/url.php b/e107_core/url/news/url.php index d3fc8962f..9c0061937 100644 --- a/e107_core/url/news/url.php +++ b/e107_core/url/news/url.php @@ -1,208 +1,208 @@ - array( - 'allowMain' => false, // [optional] default false; disallow this module (while using this config) to be set as site main URL namespace - 'noSingleEntry' => true, // [optional] default false; disallow this module to be shown via single entry point when this config is used - 'legacy' => '{e_BASE}news.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script - 'format' => 'get', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'selfParse' => true, // [optional] default false; use only this->parse() method, no core routine URL parsing - 'selfCreate' => true, // [optional] default false; use only this->create() method, no core routine URL creating - 'defaultRoute' => 'list/new',// [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - 'errorRoute' => '', // [optional] default empty; route (no leading module) used when module is found but no inner route is matched, leave empty to force error 404 page - 'urlSuffix' => '', // [optional] default empty; string to append to the URL (e.g. .html), not used when format is 'get' or legacy non-empty - - ### [optional] used only when assembling URLs via rules(); - ### if 'empty' - check if the required parameter is empty (results in assemble fail), - ### if 1 or true - it uses the route pattern to match every parameter - EXTREMELY SLOW, be warned - 'matchValue' => false, - - - ### [optional] vars mapping (create URL routine), override per rule is allowed - ### Keys of this array will be used as a map for finding values from the provided parameters array. - ### Those values will be assigned to new keys - corresponding values of mapVars array - ### It gives extremely flexibility when used with allowVars. For example we pass $news item array as - ### it's retrieved from the DB, with no modifications. This gives us the freedom to create any variations of news - ### URLs using the DB data with a single line URL rule. Another aspect of this feature is the simplified code - ### for URL assembling - we just do eRouter::create($theRoute, $newsDbArray) - ### Not used when in selfCreate mod (create url) - 'mapVars' => array( - //'news_id' => 'id', - //'news_sef' => 'name', - ), - - ### [optional] allowed vars definition (create URL routine), override per rule is allowed - ### This numerical array serves as a filter for passed vars when creating URLs - ### Everything outside this scope is ignored while assembling URLs. Exception are route variables. - ### For example: when is present in the route string, there is no need to extra allow 'id' - ### To disallow everything but route variables, set allowVars to false - ### When format is get, false value will disallow everything (no params) and default preserved variables - ### will be extracted from mapVars (if available) - ### Default value is empty array - ### Not used when in selfCreate mod (create url) - 'allowVars' => array(/*'page', 'name'*/), - - ### Those are regex templates, allowing us to avoid the repeating regex patterns writing in your rules. - ### varTemplates are merged with the core predefined templates. Full list with core regex templates and examples can be found - ### in rewrite_extended news URL config - 'varTemplates' => array(/*'testIt' => '[\d]+'*/), - ), - - 'rules' => array(), // rule set array - can't be used with format 'get' and noSingleEntry true - ); - } - - /** - * If create returns string, 'module' value won't be prefixed from the router - * Query mapping in format route?params: - * - view/item?id=xxx -> ?extend.id - * - list/items[?page=xxx] -> default.0.page - * - list/category?id=xxx[&page=xxx] -> list.id.page - * - list/category?id=0[&page=xxx] -> default.0.page - * - list/short?id=xxx[&page=xxx] -> cat.id.page - * - list/day?id=xxx -> ?day-id - * - list/month?id=xxx -> ?month-id - * - list/year?id=xxx -> ?year-id - * - list/nextprev?route=xxx -> PARSED_ROUTE.[FROM] (recursive parse() call) - */ - public function create($route, $params = array(),$options = array()) - { - if(!$params) return 'news.php'; - - if(!$route) $route = 'list/items'; - if(is_string($route)) $route = explode('/', $route, 2); - if('index' == $route[0]) - { - $route[0] = 'list'; - $route[1] = 'items'; - } - elseif('index' == $route[1]) - { - $route[1] = 'items'; - } - - // return print_a($route,true); - ## news are passing array as it is retrieved from the DB, map vars to proper values - if(isset($params['news_id']) && !empty($params['news_id'])) $params['id'] = $params['news_id']; - //if(isset($params['news_sef']) && !empty($params['news_sef'])) $params['id'] = $params['news_sef']; - //if(isset($params['category_sef']) && !empty($params['category_sef'])) $params['category'] = $params['category_sef']; - - $url = 'news.php?'; - if('--FROM--' != vartrue($params['page'])) $page = varset($params['page']) ? intval($params['page']) : '0'; - else $page = '--FROM--'; - - if($route[0] == 'view') - { - switch ($route[1]) - { - case 'item': - $url .= 'extend.'.$params['id']; //item.* view is deprecated - break; - - default: - $url = 'news.php'; - break; - } - } - elseif($route[0] == 'list') - { - switch ($route[1]) - { - case '': - case 'items': - if(!$page) $url = 'news.php'; - else $url .= 'default.0.'.$page; //item.* view is deprecated - break; - - case 'category': - if(!vartrue($params['id'])) - { - $url .= 'default.0.'.$page; - } - else - { - $url .= 'list.'.$params['id'].'.'.$page; // 'category_id' would break news_categories_menu. - } - break; - - case 'all': - $url .= 'all.'.$params['id'].'.'.$page; - break; - - case 'tag': - $url .= 'tag='.$params['tag'].'&page='.$page; - break; - - case 'author': - $url .= 'author='.$params['author'].'&page='.$page; - break; - - case 'short': - $url .= 'cat.'.$params['id'].'.'.$page; - break; - - case 'day': - case 'month': - case 'year': - if($page) $page = '.'.$page; - $url .= $route[1].'.'.$params['id'].$page; - break; - - default: - $url = 'news.php'; - break; - } - } - else - { - $url = 'news.php'; - } - - return $url; - } - - public function parse($pathInfo, $params = array(), eRequest $request = null, eRouter $router = null, $config = array()) - { - // this config doesn't support parsing, it's done by the module entry script (news.php) - // this means News are not available via single entry point if this config is currently active - return false; - } - - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - 'labels' => array( - 'name' => LAN_EURL_CORE_NEWS, // Module name - 'label' => LAN_EURL_DEFAULT, // Current profile name - 'description' => LAN_EURL_LEGACY, // - 'examples' => array("{SITEURL}news.php?extend.1") - ), - // 'generate' => array('table'=> 'news', 'primary'=>'news_id', 'input'=>'news_title', 'output'=>'news_sef'), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } -} - + array( + 'allowMain' => false, // [optional] default false; disallow this module (while using this config) to be set as site main URL namespace + 'noSingleEntry' => true, // [optional] default false; disallow this module to be shown via single entry point when this config is used + 'legacy' => '{e_BASE}news.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script + 'format' => 'get', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored + 'selfParse' => true, // [optional] default false; use only this->parse() method, no core routine URL parsing + 'selfCreate' => true, // [optional] default false; use only this->create() method, no core routine URL creating + 'defaultRoute' => 'list/new',// [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ + 'errorRoute' => '', // [optional] default empty; route (no leading module) used when module is found but no inner route is matched, leave empty to force error 404 page + 'urlSuffix' => '', // [optional] default empty; string to append to the URL (e.g. .html), not used when format is 'get' or legacy non-empty + + ### [optional] used only when assembling URLs via rules(); + ### if 'empty' - check if the required parameter is empty (results in assemble fail), + ### if 1 or true - it uses the route pattern to match every parameter - EXTREMELY SLOW, be warned + 'matchValue' => false, + + + ### [optional] vars mapping (create URL routine), override per rule is allowed + ### Keys of this array will be used as a map for finding values from the provided parameters array. + ### Those values will be assigned to new keys - corresponding values of mapVars array + ### It gives extremely flexibility when used with allowVars. For example we pass $news item array as + ### it's retrieved from the DB, with no modifications. This gives us the freedom to create any variations of news + ### URLs using the DB data with a single line URL rule. Another aspect of this feature is the simplified code + ### for URL assembling - we just do eRouter::create($theRoute, $newsDbArray) + ### Not used when in selfCreate mod (create url) + 'mapVars' => array( + //'news_id' => 'id', + //'news_sef' => 'name', + ), + + ### [optional] allowed vars definition (create URL routine), override per rule is allowed + ### This numerical array serves as a filter for passed vars when creating URLs + ### Everything outside this scope is ignored while assembling URLs. Exception are route variables. + ### For example: when is present in the route string, there is no need to extra allow 'id' + ### To disallow everything but route variables, set allowVars to false + ### When format is get, false value will disallow everything (no params) and default preserved variables + ### will be extracted from mapVars (if available) + ### Default value is empty array + ### Not used when in selfCreate mod (create url) + 'allowVars' => array(/*'page', 'name'*/), + + ### Those are regex templates, allowing us to avoid the repeating regex patterns writing in your rules. + ### varTemplates are merged with the core predefined templates. Full list with core regex templates and examples can be found + ### in rewrite_extended news URL config + 'varTemplates' => array(/*'testIt' => '[\d]+'*/), + ), + + 'rules' => array(), // rule set array - can't be used with format 'get' and noSingleEntry true + ); + } + + /** + * If create returns string, 'module' value won't be prefixed from the router + * Query mapping in format route?params: + * - view/item?id=xxx -> ?extend.id + * - list/items[?page=xxx] -> default.0.page + * - list/category?id=xxx[&page=xxx] -> list.id.page + * - list/category?id=0[&page=xxx] -> default.0.page + * - list/short?id=xxx[&page=xxx] -> cat.id.page + * - list/day?id=xxx -> ?day-id + * - list/month?id=xxx -> ?month-id + * - list/year?id=xxx -> ?year-id + * - list/nextprev?route=xxx -> PARSED_ROUTE.[FROM] (recursive parse() call) + */ + public function create($route, $params = array(),$options = array()) + { + if(!$params) return 'news.php'; + + if(!$route) $route = 'list/items'; + if(is_string($route)) $route = explode('/', $route, 2); + if('index' == $route[0]) + { + $route[0] = 'list'; + $route[1] = 'items'; + } + elseif('index' == $route[1]) + { + $route[1] = 'items'; + } + + // return print_a($route,true); + ## news are passing array as it is retrieved from the DB, map vars to proper values + if(isset($params['news_id']) && !empty($params['news_id'])) $params['id'] = $params['news_id']; + //if(isset($params['news_sef']) && !empty($params['news_sef'])) $params['id'] = $params['news_sef']; + //if(isset($params['category_sef']) && !empty($params['category_sef'])) $params['category'] = $params['category_sef']; + + $url = 'news.php?'; + if('--FROM--' != vartrue($params['page'])) $page = varset($params['page']) ? intval($params['page']) : '0'; + else $page = '--FROM--'; + + if($route[0] == 'view') + { + switch ($route[1]) + { + case 'item': + $url .= 'extend.'.$params['id']; //item.* view is deprecated + break; + + default: + $url = 'news.php'; + break; + } + } + elseif($route[0] == 'list') + { + switch ($route[1]) + { + case '': + case 'items': + if(!$page) $url = 'news.php'; + else $url .= 'default.0.'.$page; //item.* view is deprecated + break; + + case 'category': + if(!vartrue($params['id'])) + { + $url .= 'default.0.'.$page; + } + else + { + $url .= 'list.'.$params['id'].'.'.$page; // 'category_id' would break news_categories_menu. + } + break; + + case 'all': + $url .= 'all.'.$params['id'].'.'.$page; + break; + + case 'tag': + $url .= 'tag='.$params['tag'].'&page='.$page; + break; + + case 'author': + $url .= 'author='.$params['author'].'&page='.$page; + break; + + case 'short': + $url .= 'cat.'.$params['id'].'.'.$page; + break; + + case 'day': + case 'month': + case 'year': + if($page) $page = '.'.$page; + $url .= $route[1].'.'.$params['id'].$page; + break; + + default: + $url = 'news.php'; + break; + } + } + else + { + $url = 'news.php'; + } + + return $url; + } + + public function parse($pathInfo, $params = array(), eRequest $request = null, eRouter $router = null, $config = array()) + { + // this config doesn't support parsing, it's done by the module entry script (news.php) + // this means News are not available via single entry point if this config is currently active + return false; + } + + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + 'labels' => array( + 'name' => LAN_EURL_CORE_NEWS, // Module name + 'label' => LAN_EURL_DEFAULT, // Current profile name + 'description' => LAN_EURL_LEGACY, // + 'examples' => array("{SITEURL}news.php?extend.1") + ), + // 'generate' => array('table'=> 'news', 'primary'=>'news_id', 'input'=>'news_title', 'output'=>'news_sef'), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } +} + diff --git a/e107_core/url/page/sef_noid_url.php b/e107_core/url/page/sef_noid_url.php index 1bfccff7a..456f8384e 100644 --- a/e107_core/url/page/sef_noid_url.php +++ b/e107_core/url/page/sef_noid_url.php @@ -1,151 +1,151 @@ - array( - 'allowMain' => true, - 'legacy' => '{e_BASE}page.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script - 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'defaultRoute' => 'view/index',// [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - 'urlSuffix' => '', // [optional] default empty; string to append to the URL (e.g. .html) - - 'allowVars' => array( - 'page', - ), - ), - - 'rules' => array( - 'chapter/' => array('chapter/index', 'allowVars' => false, 'mapVars' => array('chapter_id'=>'id', 'chapter_sef'=>'name'), 'legacyQuery' => 'ch={id}', 'parseCallback' => 'chapterIdByTitle'), - 'book/' => array('book/index', 'allowVars' => false, 'mapVars' => array('chapter_id'=>'id', 'chapter_sef'=>'name'), 'legacyQuery' => 'bk={id}', 'parseCallback' => 'chapterIdByTitle'), - '' => array('view/index', 'mapVars' => array('page_id'=>'id', 'page_sef'=>'name'), 'legacyQuery' => '{id}.{page}', 'parseCallback' => 'itemIdByTitle'), - ### Used for assembling only - '' => array('view/other', 'mapVars' => array('page_id'=>'id', 'page_sef'=>'other'), 'legacyQuery' => '{id}.{page}', 'parseCallback' => 'itemIdByTitle'), - '/' => array('list/index', 'allowVars' => false, 'legacyQuery' => '', ), // page list - ) - ); - } - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - 'labels' => array( - 'name' => LAN_EURL_CORE_PAGE, // Module name - 'label' => LAN_EURL_PAGE_SEFNOID_LABEL, // Current profile name - 'description' => LAN_EURL_PAGE_SEFNOID_DESCR, // - 'examples' => array("{SITEURL}page/page-title") - ), - 'generate' => array('table'=> 'page', 'primary'=>'page_id', 'input'=>'page_title', 'output'=>'page_sef'), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } - - ### CUSTOM METHODS ### - - /** - * view/item by name callback - * @param eRequest $request - */ - public function itemIdByTitle(eRequest $request) - { - $name = $request->getRequestParam('name'); - - // e107::getMessage()->addDebug('name = '.$name); - // e107::getMessage()->addDebug(print_r($request,true)); - // e107::getAdminLog()->toFile('page_sef_noid_url'); - - if(($id = $request->getRequestParam('id'))) - { - $request->setRequestParam('name', $id); - return; - } - elseif(!$name || is_numeric($name)) - { - if(ADMIN) - { - e107::getMessage()->addError("One of your pages is missing a SEF URL value"); - } - return; - } - - $sql = e107::getDb('url'); - $name = e107::getParser()->toDB($name); - - if($sql->select('page', 'page_id', "page_sef='{$name}'")) - { - $name = $sql->fetch(); - $request->setRequestParam('name', $name['page_id']) - ->setRequestParam('id', $name['page_id']); - } - else - { - if(ADMIN) - { - e107::getMessage()->addError("Couldn't find a page with a SEF URL value of '".$name."'"); - } - $request->setRequestParam('name', 0) - ->setRequestParam('id', 0); - } - } - - /** - * chapter/index and book/index by name callback - * @param eRequest $request - */ - public function chapterIdByTitle(eRequest $request) - { - $name = $request->getRequestParam('name'); - - if(($id = $request->getRequestParam('id'))) - { - $request->setRequestParam('name', $id); - return; - } - elseif(!$name || is_numeric($name)) - { - if(ADMIN) - { - e107::getMessage()->addError("One of your page-chapters is missing a SEF URL value"); - } - return; - } - - $sql = e107::getDb('url'); - $name = e107::getParser()->toDB($name); - - if($sql->select('page_chapters', 'chapter_id', "chapter_sef='{$name}'")) - { - $name = $sql->fetch(); - $request->setRequestParam('id', $name['chapter_id']) - ->setRequestParam('name', $name['chapter_id']); - } - else - { - if(ADMIN) - { - e107::getMessage()->addError("Couldn't find a book or chapter with a SEF URL value of '".$name."'"); - } - $request->setRequestParam('id', 0) - ->setRequestParam('name', 0); - } - } - -} + array( + 'allowMain' => true, + 'legacy' => '{e_BASE}page.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script + 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored + 'defaultRoute' => 'view/index',// [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ + 'urlSuffix' => '', // [optional] default empty; string to append to the URL (e.g. .html) + + 'allowVars' => array( + 'page', + ), + ), + + 'rules' => array( + 'chapter/' => array('chapter/index', 'allowVars' => false, 'mapVars' => array('chapter_id'=>'id', 'chapter_sef'=>'name'), 'legacyQuery' => 'ch={id}', 'parseCallback' => 'chapterIdByTitle'), + 'book/' => array('book/index', 'allowVars' => false, 'mapVars' => array('chapter_id'=>'id', 'chapter_sef'=>'name'), 'legacyQuery' => 'bk={id}', 'parseCallback' => 'chapterIdByTitle'), + '' => array('view/index', 'mapVars' => array('page_id'=>'id', 'page_sef'=>'name'), 'legacyQuery' => '{id}.{page}', 'parseCallback' => 'itemIdByTitle'), + ### Used for assembling only + '' => array('view/other', 'mapVars' => array('page_id'=>'id', 'page_sef'=>'other'), 'legacyQuery' => '{id}.{page}', 'parseCallback' => 'itemIdByTitle'), + '/' => array('list/index', 'allowVars' => false, 'legacyQuery' => '', ), // page list + ) + ); + } + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + 'labels' => array( + 'name' => LAN_EURL_CORE_PAGE, // Module name + 'label' => LAN_EURL_PAGE_SEFNOID_LABEL, // Current profile name + 'description' => LAN_EURL_PAGE_SEFNOID_DESCR, // + 'examples' => array("{SITEURL}page/page-title") + ), + 'generate' => array('table'=> 'page', 'primary'=>'page_id', 'input'=>'page_title', 'output'=>'page_sef'), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } + + ### CUSTOM METHODS ### + + /** + * view/item by name callback + * @param eRequest $request + */ + public function itemIdByTitle(eRequest $request) + { + $name = $request->getRequestParam('name'); + + // e107::getMessage()->addDebug('name = '.$name); + // e107::getMessage()->addDebug(print_r($request,true)); + // e107::getAdminLog()->toFile('page_sef_noid_url'); + + if(($id = $request->getRequestParam('id'))) + { + $request->setRequestParam('name', $id); + return; + } + elseif(!$name || is_numeric($name)) + { + if(ADMIN) + { + e107::getMessage()->addError("One of your pages is missing a SEF URL value"); + } + return; + } + + $sql = e107::getDb('url'); + $name = e107::getParser()->toDB($name); + + if($sql->select('page', 'page_id', "page_sef='{$name}'")) + { + $name = $sql->fetch(); + $request->setRequestParam('name', $name['page_id']) + ->setRequestParam('id', $name['page_id']); + } + else + { + if(ADMIN) + { + e107::getMessage()->addError("Couldn't find a page with a SEF URL value of '".$name."'"); + } + $request->setRequestParam('name', 0) + ->setRequestParam('id', 0); + } + } + + /** + * chapter/index and book/index by name callback + * @param eRequest $request + */ + public function chapterIdByTitle(eRequest $request) + { + $name = $request->getRequestParam('name'); + + if(($id = $request->getRequestParam('id'))) + { + $request->setRequestParam('name', $id); + return; + } + elseif(!$name || is_numeric($name)) + { + if(ADMIN) + { + e107::getMessage()->addError("One of your page-chapters is missing a SEF URL value"); + } + return; + } + + $sql = e107::getDb('url'); + $name = e107::getParser()->toDB($name); + + if($sql->select('page_chapters', 'chapter_id', "chapter_sef='{$name}'")) + { + $name = $sql->fetch(); + $request->setRequestParam('id', $name['chapter_id']) + ->setRequestParam('name', $name['chapter_id']); + } + else + { + if(ADMIN) + { + e107::getMessage()->addError("Couldn't find a book or chapter with a SEF URL value of '".$name."'"); + } + $request->setRequestParam('id', 0) + ->setRequestParam('name', 0); + } + } + +} diff --git a/e107_core/url/page/sef_url.php b/e107_core/url/page/sef_url.php index 4895c0d76..248159c5d 100644 --- a/e107_core/url/page/sef_url.php +++ b/e107_core/url/page/sef_url.php @@ -1,67 +1,67 @@ - array( - 'allowMain' => true, - 'legacy' => '{e_BASE}page.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script - 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'defaultRoute' => 'view/index',// [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - 'urlSuffix' => '', // [optional] default empty; string to append to the URL (e.g. .html) - - 'mapVars' => array( - 'page_id' => 'id', - 'page_sef' => 'name', - ), - - 'allowVars' => array( - 'page', - ), - ), - - 'rules' => array( - '/' => array('view/index', 'legacyQuery' => '{id}.{page}', ), - ### Used for assembling only - '/' => array('view/other', 'mapVars' => array('page_id'=>'id', 'page_sef'=>'other'), 'legacyQuery' => '{id}.{page}', ), - 'chapter//' => array('chapter/index', 'allowVars' => false, 'mapVars' => array('chapter_id'=>'id','chapter_sef'=>'name'), 'legacyQuery' => 'ch={id}' ), - 'book//' => array('book/index', 'allowVars' => false, 'mapVars' => array('chapter_id'=>'id','chapter_sef'=>'name'), 'legacyQuery' => 'bk={id}' ), - - ### page list - '/' => array('list/index', 'legacyQuery' => '', ), - ) // rule set array - ); - } - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - 'labels' => array( - 'name' => LAN_EURL_CORE_PAGE, // Module name - 'label' => LAN_EURL_PAGE_SEF_LABEL, // Current profile name - 'description' => LAN_EURL_PAGE_SEF_DESCR, // - 'examples' => array("{SITEURL}page/1/page-name") - ), - 'generate' => array('table'=> 'page', 'primary'=>'page_id', 'input'=>'page_title', 'output'=>'page_sef'), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } -} + array( + 'allowMain' => true, + 'legacy' => '{e_BASE}page.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script + 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored + 'defaultRoute' => 'view/index',// [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ + 'urlSuffix' => '', // [optional] default empty; string to append to the URL (e.g. .html) + + 'mapVars' => array( + 'page_id' => 'id', + 'page_sef' => 'name', + ), + + 'allowVars' => array( + 'page', + ), + ), + + 'rules' => array( + '/' => array('view/index', 'legacyQuery' => '{id}.{page}', ), + ### Used for assembling only + '/' => array('view/other', 'mapVars' => array('page_id'=>'id', 'page_sef'=>'other'), 'legacyQuery' => '{id}.{page}', ), + 'chapter//' => array('chapter/index', 'allowVars' => false, 'mapVars' => array('chapter_id'=>'id','chapter_sef'=>'name'), 'legacyQuery' => 'ch={id}' ), + 'book//' => array('book/index', 'allowVars' => false, 'mapVars' => array('chapter_id'=>'id','chapter_sef'=>'name'), 'legacyQuery' => 'bk={id}' ), + + ### page list + '/' => array('list/index', 'legacyQuery' => '', ), + ) // rule set array + ); + } + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + 'labels' => array( + 'name' => LAN_EURL_CORE_PAGE, // Module name + 'label' => LAN_EURL_PAGE_SEF_LABEL, // Current profile name + 'description' => LAN_EURL_PAGE_SEF_DESCR, // + 'examples' => array("{SITEURL}page/1/page-name") + ), + 'generate' => array('table'=> 'page', 'primary'=>'page_id', 'input'=>'page_title', 'output'=>'page_sef'), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } +} diff --git a/e107_core/url/page/url.php b/e107_core/url/page/url.php index af5fee67f..5fa79f3b7 100644 --- a/e107_core/url/page/url.php +++ b/e107_core/url/page/url.php @@ -1,131 +1,131 @@ - array( - 'noSingleEntry' => true, // [optional] default false; disallow this module to be shown via single entry point when this config is used - 'legacy' => '{e_BASE}page.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script - 'format' => 'get', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'selfParse' => true, // [optional] default false; use only this->parse() method, no core routine URL parsing - 'selfCreate' => true, // [optional] default false; use only this->create() method, no core routine URL creating - 'defaultRoute' => '', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - 'errorRoute' => '', // [optional] default empty; route (no leading module) used when module is found but no inner route is matched, leave empty to force error 404 page - 'urlSuffix' => '', // [optional] default empty; string to append to the URL (e.g. .html) - 'mapVars' => array(), - 'allowVars' => array(), - ), - - 'rules' => array() // rule set array - ); - } - - /** - * - */ - public function create($route, $params = array(), $options = array()) - { - if(!$params) return 'page.php'; - - if(is_string($route)) - { - $route = explode('/', $route, 2); - - } - - - if(!varset($route[1])) $route[1] = 'index'; - - $url = 'page.php?'; - - if(isset($params['chapter_id']) && !empty($params['chapter_id'])) - { - $params['id'] = $params['chapter_id']; - } - - switch ($route[0]) - { - case 'book': - - if(!empty($params['book_id'])) - { - $params['id'] = $params['book_id']; - } - - $url .= "bk=".intval($params['id']); - break; - - case 'chapter': - $url .= "ch=".intval($params['id']); - break; - - case 'view': - default: - ## aliases as retrieved from the DB, map vars to proper values - if(isset($params['page_title']) && !empty($params['page_title'])) - { - $params['name'] = $params['page_title']; - } - - if(isset($params['page_id']) && !empty($params['page_id'])) - { - $params['id'] = $params['page_id']; - } - - if('--FROM--' != vartrue($params['page'])) - { - $page = varset($params['page']) ? intval($params['page']) : '0'; - } - else - { - $page = '--FROM--'; - } - - $url .= "id=".intval($params['id']).($page ? '.'.$page : ''); - break; - - - } - - - return $url; - } - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - 'labels' => array( - 'name' => LAN_EURL_CORE_PAGE, // Module name - 'label' => LAN_EURL_DEFAULT, // Current profile name - 'description' => LAN_EURL_LEGACY, // - 'examples' => array("{SITEURL}page.php?1","{SITEURL}page.php?id=1") - ), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } - - public function parse($pathInfo, $params = array(), eRequest $request = null, eRouter $router = null, $config = array()) - { - // this config doesn't support parsing, it's done by the module entry script (news.php) - // this means News are not available via single entry point if this config is currently active - return false; - } -} + array( + 'noSingleEntry' => true, // [optional] default false; disallow this module to be shown via single entry point when this config is used + 'legacy' => '{e_BASE}page.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script + 'format' => 'get', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored + 'selfParse' => true, // [optional] default false; use only this->parse() method, no core routine URL parsing + 'selfCreate' => true, // [optional] default false; use only this->create() method, no core routine URL creating + 'defaultRoute' => '', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ + 'errorRoute' => '', // [optional] default empty; route (no leading module) used when module is found but no inner route is matched, leave empty to force error 404 page + 'urlSuffix' => '', // [optional] default empty; string to append to the URL (e.g. .html) + 'mapVars' => array(), + 'allowVars' => array(), + ), + + 'rules' => array() // rule set array + ); + } + + /** + * + */ + public function create($route, $params = array(), $options = array()) + { + if(!$params) return 'page.php'; + + if(is_string($route)) + { + $route = explode('/', $route, 2); + + } + + + if(!varset($route[1])) $route[1] = 'index'; + + $url = 'page.php?'; + + if(isset($params['chapter_id']) && !empty($params['chapter_id'])) + { + $params['id'] = $params['chapter_id']; + } + + switch ($route[0]) + { + case 'book': + + if(!empty($params['book_id'])) + { + $params['id'] = $params['book_id']; + } + + $url .= "bk=".intval($params['id']); + break; + + case 'chapter': + $url .= "ch=".intval($params['id']); + break; + + case 'view': + default: + ## aliases as retrieved from the DB, map vars to proper values + if(isset($params['page_title']) && !empty($params['page_title'])) + { + $params['name'] = $params['page_title']; + } + + if(isset($params['page_id']) && !empty($params['page_id'])) + { + $params['id'] = $params['page_id']; + } + + if('--FROM--' != vartrue($params['page'])) + { + $page = varset($params['page']) ? intval($params['page']) : '0'; + } + else + { + $page = '--FROM--'; + } + + $url .= "id=".intval($params['id']).($page ? '.'.$page : ''); + break; + + + } + + + return $url; + } + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + 'labels' => array( + 'name' => LAN_EURL_CORE_PAGE, // Module name + 'label' => LAN_EURL_DEFAULT, // Current profile name + 'description' => LAN_EURL_LEGACY, // + 'examples' => array("{SITEURL}page.php?1","{SITEURL}page.php?id=1") + ), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } + + public function parse($pathInfo, $params = array(), eRequest $request = null, eRouter $router = null, $config = array()) + { + // this config doesn't support parsing, it's done by the module entry script (news.php) + // this means News are not available via single entry point if this config is currently active + return false; + } +} diff --git a/e107_core/url/search/rewrite_url.php b/e107_core/url/search/rewrite_url.php index 3b1fa5354..f4f288616 100644 --- a/e107_core/url/search/rewrite_url.php +++ b/e107_core/url/search/rewrite_url.php @@ -1,50 +1,50 @@ - array( - 'legacy' => '{e_BASE}search.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script to be included - 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'defaultRoute' => 'index/index', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - - ), - - // rule set array - 'rules' => array( - '/' => array('index/index', 'defaultVars' => array('id' => 0)), - ) - ); - } - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - 'labels' => array( - 'name' => LAN_EURL_CORE_SEARCH, // Module name - 'label' => LAN_EURL_SEARCH_REWRITE_LABEL, // Current profile name - 'description' => LAN_EURL_SEARCH_REWRITE_DESCR, // - 'examples' => array("{SITEURL}search/") - ), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } -} + array( + 'legacy' => '{e_BASE}search.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script to be included + 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored + 'defaultRoute' => 'index/index', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ + + ), + + // rule set array + 'rules' => array( + '/' => array('index/index', 'defaultVars' => array('id' => 0)), + ) + ); + } + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + 'labels' => array( + 'name' => LAN_EURL_CORE_SEARCH, // Module name + 'label' => LAN_EURL_SEARCH_REWRITE_LABEL, // Current profile name + 'description' => LAN_EURL_SEARCH_REWRITE_DESCR, // + 'examples' => array("{SITEURL}search/") + ), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } +} diff --git a/e107_core/url/search/url.php b/e107_core/url/search/url.php index 1c758910c..ffc814769 100644 --- a/e107_core/url/search/url.php +++ b/e107_core/url/search/url.php @@ -1,67 +1,67 @@ - array( - 'noSingleEntry' => true, // [optional] default false; disallow this module to be shown via single entry point when this config is used - 'legacy' => '{e_BASE}search.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script - 'format' => 'get', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'selfParse' => true, // [optional] default false; use only this->parse() method, no core routine URL parsing - 'selfCreate' => true, // [optional] default false; use only this->create() method, no core routine URL creating - 'defaultRoute' => '', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - ), - - 'rules' => array() // rule set array - ); - } - - /** - * Query mapping - */ - public function create($route, $params = array(), $options=array()) - { - if(!$params) return 'search.php'; - - return 'search.php?'.eFront::instance()->getRouter()->createPathInfo($params, $options); - } - - /* - public function parse($pathInfo) - { - // this config doesn't support parsing, it's done by the module entry script (search.php) - // this means Search is not available via single entry point if this config is currently active - return false; - }*/ - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - 'labels' => array( - 'name' => LAN_EURL_CORE_SEARCH, // Module name - 'label' => LAN_EURL_DEFAULT, // Current profile name - 'description' => LAN_EURL_LEGACY, // - 'examples' => array("{SITEURL}search.php") - ), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } -} + array( + 'noSingleEntry' => true, // [optional] default false; disallow this module to be shown via single entry point when this config is used + 'legacy' => '{e_BASE}search.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script + 'format' => 'get', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored + 'selfParse' => true, // [optional] default false; use only this->parse() method, no core routine URL parsing + 'selfCreate' => true, // [optional] default false; use only this->create() method, no core routine URL creating + 'defaultRoute' => '', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ + ), + + 'rules' => array() // rule set array + ); + } + + /** + * Query mapping + */ + public function create($route, $params = array(), $options=array()) + { + if(!$params) return 'search.php'; + + return 'search.php?'.eFront::instance()->getRouter()->createPathInfo($params, $options); + } + + /* + public function parse($pathInfo) + { + // this config doesn't support parsing, it's done by the module entry script (search.php) + // this means Search is not available via single entry point if this config is currently active + return false; + }*/ + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + 'labels' => array( + 'name' => LAN_EURL_CORE_SEARCH, // Module name + 'label' => LAN_EURL_DEFAULT, // Current profile name + 'description' => LAN_EURL_LEGACY, // + 'examples' => array("{SITEURL}search.php") + ), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } +} diff --git a/e107_core/url/system/rewrite_url.php b/e107_core/url/system/rewrite_url.php index 3a2aa7f30..93da45d88 100644 --- a/e107_core/url/system/rewrite_url.php +++ b/e107_core/url/system/rewrite_url.php @@ -1,53 +1,53 @@ - array( - 'allowMain' => true, - 'format' => 'path', - 'defaultRoute' => 'error/notfound', - 'errorRoute' => 'error/notfound', - - ), - - // rule set array - 'rules' => array( - 'error404' => 'error/notfound', - 'hello' => 'error/hello-world', - '/' => '/', - ) - ); - } - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - 'labels' => array( - 'name' => LAN_EURL_CORE_SYSTEM, // Module name - 'label' => LAN_EURL_SYSTEM_REWRITE_LABEL, // Current profile name - 'description' => LAN_EURL_SYSTEM_REWRITE_DESCR, // - 'examples' => array("{SITEURL}system/error/404") - ), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } -} + array( + 'allowMain' => true, + 'format' => 'path', + 'defaultRoute' => 'error/notfound', + 'errorRoute' => 'error/notfound', + + ), + + // rule set array + 'rules' => array( + 'error404' => 'error/notfound', + 'hello' => 'error/hello-world', + '/' => '/', + ) + ); + } + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + 'labels' => array( + 'name' => LAN_EURL_CORE_SYSTEM, // Module name + 'label' => LAN_EURL_SYSTEM_REWRITE_LABEL, // Current profile name + 'description' => LAN_EURL_SYSTEM_REWRITE_DESCR, // + 'examples' => array("{SITEURL}system/error/404") + ), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } +} diff --git a/e107_core/url/system/url.php b/e107_core/url/system/url.php index 3fd719131..c37a6d552 100644 --- a/e107_core/url/system/url.php +++ b/e107_core/url/system/url.php @@ -1,44 +1,44 @@ - array( - 'format' => 'get', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'defaultRoute' => 'error/notfound', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - - ), - ); - } - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - 'labels' => array( - 'name' => LAN_EURL_CORE_SYSTEM, // Module name - 'label' => LAN_EURL_SYSTEM_DEFAULT_LABEL, // Current profile name - 'description' => LAN_EURL_SYSTEM_DEFAULT_DESCR, // - 'examples' => array("{SITEURL}?route=system/error/notfound") - ), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } -} + array( + 'format' => 'get', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored + 'defaultRoute' => 'error/notfound', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ + + ), + ); + } + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + 'labels' => array( + 'name' => LAN_EURL_CORE_SYSTEM, // Module name + 'label' => LAN_EURL_SYSTEM_DEFAULT_LABEL, // Current profile name + 'description' => LAN_EURL_SYSTEM_DEFAULT_DESCR, // + 'examples' => array("{SITEURL}?route=system/error/notfound") + ), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } +} diff --git a/e107_core/url/user/rewrite_url.php b/e107_core/url/user/rewrite_url.php index f0e31a309..fcd795b37 100644 --- a/e107_core/url/user/rewrite_url.php +++ b/e107_core/url/user/rewrite_url.php @@ -1,102 +1,102 @@ - array( - 'noSingleEntry' => false, // [optional] default false; disallow this module to be shown via single entry point when this config is used - 'legacy' => '{e_BASE}user.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script to be included - 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'selfParse' => false, // [optional] default false; use only this->parse() method, no core routine URL parsing - 'selfCreate' => false, // [optional] default false; use only this->create() method, no core routine URL creating - 'defaultRoute' => 'myprofile/view', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - 'errorRoute' => '', // [optional] default empty; route (no leading module) used when module is found but no inner route is matched, leave empty to force error 404 page - 'urlSuffix' => '', // [optional] default empty; string to append to the URL (e.g. .html) - 'mapVars' => array( // vars mapping (create URL) - 'user_id' => 'id', - 'user_name' => 'name', - ), - 'allowVars' => false, // allowed vars (create URL, used for legacyQuery parsing in parse routine as well), false means - disallow all vars beside those required by the rules - 'legacyQuery' => '' // default legacy query string template, null to disable, override possible by rule - ), - - // rule set array - 'rules' => array( - // simple matches first - PERFORMANCE - '' => array('myprofile/view', 'defaultVars' => array('id' => 0)), - 'settings' => array('myprofile/edit', 'defaultVars' => array('id' => 0), 'legacy' => '{e_BASE}usersettings.php'), - 'list' => array('profile/list', 'allowVars' => array('page'), 'legacyQuery' => '{page}'), - 'login' => array('login/index', 'legacy' => '{e_BASE}login.php'), - 'register' => array('register/index', 'legacy' => '{e_BASE}signup.php'), - - // Regex involved next - //'' => array('profile/view', 'legacyQuery' => 'id.{id}'), - // 'edit/' => array('profile/edit', 'legacy' => '{e_ADMIN}users.php', 'legacyQuery' => 'mode=main&action=edit&id={id}'), - - // Named requests - important to be in the end in this order! - // 'edit/' => array('profile/edit','legacy' => '{e_ADMIN}users.php', 'legacyQuery' => 'mode=main&action=edit&id={id}', 'parseCallback' => 'idByName'), - // Last one - close to catch all! - '' => array('profile/view', 'legacyQuery' => 'id.{id}', 'parseCallback' => 'idByName'), - ) - ); - } - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - 'labels' => array( - 'name' => LAN_EURL_CORE_USER, // Module name - 'label' => LAN_EURL_USER_REWRITE_LABEL, // Current profile name - 'description' => LAN_EURL_USER_REWRITE_DESCR, // - 'examples' => array("{SITEURL}user/UserDisplayName") - ), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } - - ### CUSTOM METHODS ### - - /** - * profile/edit & profile/view callback - * @param eRequest $request - */ - public function idByName(eRequest $request) - { - $name = $request->getRequestParam('name'); - if(!$name) return; - - // if id only is passed, don't do DB query - if(is_numeric($name)) - { - $request->setRequestParam('id', $name)->setRequestParam('name', null); - return; - } - - $sql = e107::getDb('url'); - $name = e107::getParser()->toDB($name); - - if($sql->select('user', 'user_id', "user_name='{$name}' OR REPLACE(user_name, ' ', '-') ='{$name}' " )) // XXX - new user_sef field? Discuss. - { - $name = $sql->fetch(); - $request->setRequestParam('id', $name['user_id']); - } - } -} + array( + 'noSingleEntry' => false, // [optional] default false; disallow this module to be shown via single entry point when this config is used + 'legacy' => '{e_BASE}user.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script to be included + 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored + 'selfParse' => false, // [optional] default false; use only this->parse() method, no core routine URL parsing + 'selfCreate' => false, // [optional] default false; use only this->create() method, no core routine URL creating + 'defaultRoute' => 'myprofile/view', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ + 'errorRoute' => '', // [optional] default empty; route (no leading module) used when module is found but no inner route is matched, leave empty to force error 404 page + 'urlSuffix' => '', // [optional] default empty; string to append to the URL (e.g. .html) + 'mapVars' => array( // vars mapping (create URL) + 'user_id' => 'id', + 'user_name' => 'name', + ), + 'allowVars' => false, // allowed vars (create URL, used for legacyQuery parsing in parse routine as well), false means - disallow all vars beside those required by the rules + 'legacyQuery' => '' // default legacy query string template, null to disable, override possible by rule + ), + + // rule set array + 'rules' => array( + // simple matches first - PERFORMANCE + '' => array('myprofile/view', 'defaultVars' => array('id' => 0)), + 'settings' => array('myprofile/edit', 'defaultVars' => array('id' => 0), 'legacy' => '{e_BASE}usersettings.php'), + 'list' => array('profile/list', 'allowVars' => array('page'), 'legacyQuery' => '{page}'), + 'login' => array('login/index', 'legacy' => '{e_BASE}login.php'), + 'register' => array('register/index', 'legacy' => '{e_BASE}signup.php'), + + // Regex involved next + //'' => array('profile/view', 'legacyQuery' => 'id.{id}'), + // 'edit/' => array('profile/edit', 'legacy' => '{e_ADMIN}users.php', 'legacyQuery' => 'mode=main&action=edit&id={id}'), + + // Named requests - important to be in the end in this order! + // 'edit/' => array('profile/edit','legacy' => '{e_ADMIN}users.php', 'legacyQuery' => 'mode=main&action=edit&id={id}', 'parseCallback' => 'idByName'), + // Last one - close to catch all! + '' => array('profile/view', 'legacyQuery' => 'id.{id}', 'parseCallback' => 'idByName'), + ) + ); + } + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + 'labels' => array( + 'name' => LAN_EURL_CORE_USER, // Module name + 'label' => LAN_EURL_USER_REWRITE_LABEL, // Current profile name + 'description' => LAN_EURL_USER_REWRITE_DESCR, // + 'examples' => array("{SITEURL}user/UserDisplayName") + ), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } + + ### CUSTOM METHODS ### + + /** + * profile/edit & profile/view callback + * @param eRequest $request + */ + public function idByName(eRequest $request) + { + $name = $request->getRequestParam('name'); + if(!$name) return; + + // if id only is passed, don't do DB query + if(is_numeric($name)) + { + $request->setRequestParam('id', $name)->setRequestParam('name', null); + return; + } + + $sql = e107::getDb('url'); + $name = e107::getParser()->toDB($name); + + if($sql->select('user', 'user_id', "user_name='{$name}' OR REPLACE(user_name, ' ', '-') ='{$name}' " )) // XXX - new user_sef field? Discuss. + { + $name = $sql->fetch(); + $request->setRequestParam('id', $name['user_id']); + } + } +} diff --git a/e107_core/url/user/url.php b/e107_core/url/user/url.php index ab75538ad..8ed195041 100644 --- a/e107_core/url/user/url.php +++ b/e107_core/url/user/url.php @@ -1,130 +1,130 @@ - array( - 'noSingleEntry' => true, // [optional] default false; disallow this module to be shown via single entry point when this config is used - 'legacy' => '{e_BASE}user.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script - 'format' => 'get', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'selfParse' => true, // [optional] default false; use only this->parse() method, no core routine URL parsing - 'selfCreate' => true, // [optional] default false; use only this->create() method, no core routine URL creating - 'defaultRoute' => '', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - 'errorRoute' => '', // [optional] default empty; route (no leading module) used when module is found but no inner route is matched, leave empty to force error 404 page - 'urlSuffix' => '', // [optional] default empty; string to append to the URL (e.g. .html) - 'mapVars' => array(), - 'allowVars' => array(), - ), - - 'rules' => array() // rule set array - ); - } - - /** - * Query mapping in format route?params: - * - profile/view?id=xxx -> user.php?id.xxx - * - profile/list?page=xxx -> user.php?xxx - * - myprofile/view -> user.php - * - profile/edit?id=xxx -> usersettings.php?xxx - * - myprofile/edit -> usersettings.php - * - login/index (or just 'login') -> login.php - * - register/index (or just 'register') -> signup.php - */ - public function create($route, $params = array(), $options = array()) - { - // Some routes require no params - //if(!$params) return 'user.php'; - - if(is_string($route)) $route = explode('/', $route, 2); - if(!varset($route[1])) $route[1] = 'index'; - - ## aliases as retrieved from the DB, map vars to proper values - if(isset($params['user_name']) && !empty($params['user_name'])) $params['id'] = $params['user_name']; - if(isset($params['user_id']) && !empty($params['user_id'])) $params['id'] = $params['user_id']; - - $url = 'user.php'; - $page = vartrue($params['page']) ? intval($params['page']) : '0'; - - if($route[0] == 'profile') - { - // Params required for user view, list & edit - if(!$params) return 'user.php'; - - switch ($route[1]) - { - case '': - case 'view': - $url .= '?id.'.$params['id']; - break; - - case 'list': - $url .= $page ? '?'.$page : ''; - break; - - case 'edit': - //$url = e_ADMIN_ABS."user.php?mode=main&action=edit&id=".$params['id'];// 'usersettings.php?'.$params['id']; - $url = e_ADMIN."users.php?mode=main&action=edit&id=".$params['id'];// 'usersettings.php?'.$params['id']; - break; - } - } - elseif($route[0] == 'myprofile') - { - switch ($route[1]) - { - case '': - case 'view': - // user.php - break; - - case 'edit': - $url = 'usersettings.php'; - break; - } - } - elseif($route[0] == 'login') - { - $url = 'login.php'; - } - elseif($route[0] == 'register') $url = 'signup.php'; // XXX signup URL parameters - - return $url; - } - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - static $admin = array( - 'labels' => array( - 'name' => LAN_EURL_CORE_USER, // Module name - 'label' => LAN_EURL_DEFAULT, // Current profile name - 'description' => LAN_EURL_LEGACY, // - 'examples' => array("{SITEURL}user.php?id.1") - ), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } - - public function parse($pathInfo, $params = array(), eRequest $request = NULL, eRouter $router = NULL, $config = array()) - { - // this config doesn't support parsing, it's done by the module entry script (news.php) - // this means News are not available via single entry point if this config is currently active - return false; - } -} + array( + 'noSingleEntry' => true, // [optional] default false; disallow this module to be shown via single entry point when this config is used + 'legacy' => '{e_BASE}user.php', // [optional] default empty; if it's a legacy module (no single entry point support) - URL to the entry point script + 'format' => 'get', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored + 'selfParse' => true, // [optional] default false; use only this->parse() method, no core routine URL parsing + 'selfCreate' => true, // [optional] default false; use only this->create() method, no core routine URL creating + 'defaultRoute' => '', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ + 'errorRoute' => '', // [optional] default empty; route (no leading module) used when module is found but no inner route is matched, leave empty to force error 404 page + 'urlSuffix' => '', // [optional] default empty; string to append to the URL (e.g. .html) + 'mapVars' => array(), + 'allowVars' => array(), + ), + + 'rules' => array() // rule set array + ); + } + + /** + * Query mapping in format route?params: + * - profile/view?id=xxx -> user.php?id.xxx + * - profile/list?page=xxx -> user.php?xxx + * - myprofile/view -> user.php + * - profile/edit?id=xxx -> usersettings.php?xxx + * - myprofile/edit -> usersettings.php + * - login/index (or just 'login') -> login.php + * - register/index (or just 'register') -> signup.php + */ + public function create($route, $params = array(), $options = array()) + { + // Some routes require no params + //if(!$params) return 'user.php'; + + if(is_string($route)) $route = explode('/', $route, 2); + if(!varset($route[1])) $route[1] = 'index'; + + ## aliases as retrieved from the DB, map vars to proper values + if(isset($params['user_name']) && !empty($params['user_name'])) $params['id'] = $params['user_name']; + if(isset($params['user_id']) && !empty($params['user_id'])) $params['id'] = $params['user_id']; + + $url = 'user.php'; + $page = vartrue($params['page']) ? intval($params['page']) : '0'; + + if($route[0] == 'profile') + { + // Params required for user view, list & edit + if(!$params) return 'user.php'; + + switch ($route[1]) + { + case '': + case 'view': + $url .= '?id.'.$params['id']; + break; + + case 'list': + $url .= $page ? '?'.$page : ''; + break; + + case 'edit': + //$url = e_ADMIN_ABS."user.php?mode=main&action=edit&id=".$params['id'];// 'usersettings.php?'.$params['id']; + $url = e_ADMIN."users.php?mode=main&action=edit&id=".$params['id'];// 'usersettings.php?'.$params['id']; + break; + } + } + elseif($route[0] == 'myprofile') + { + switch ($route[1]) + { + case '': + case 'view': + // user.php + break; + + case 'edit': + $url = 'usersettings.php'; + break; + } + } + elseif($route[0] == 'login') + { + $url = 'login.php'; + } + elseif($route[0] == 'register') $url = 'signup.php'; // XXX signup URL parameters + + return $url; + } + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance + static $admin = array( + 'labels' => array( + 'name' => LAN_EURL_CORE_USER, // Module name + 'label' => LAN_EURL_DEFAULT, // Current profile name + 'description' => LAN_EURL_LEGACY, // + 'examples' => array("{SITEURL}user.php?id.1") + ), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } + + public function parse($pathInfo, $params = array(), eRequest $request = NULL, eRouter $router = NULL, $config = array()) + { + // this config doesn't support parsing, it's done by the module entry script (news.php) + // this means News are not available via single entry point if this config is currently active + return false; + } +} diff --git a/e107_handlers/admin_log_class.php b/e107_handlers/admin_log_class.php index 8b6b72831..be88252bf 100644 --- a/e107_handlers/admin_log_class.php +++ b/e107_handlers/admin_log_class.php @@ -1,926 +1,926 @@ -addSuccess("Successfully executed")->save('PREF_01'); - * @example Log Only: e107::getAdminLog()->addSuccess("Successfully executed",false)->save('PREF_01'); - * @example Log Array Diff: e107::getAdminLog()->addArray($array1, $array2)->save('PREF_01'); - * @example Log Array Diff and Add to Message Handler: e107::getAdminLog()->addArray($array1, $array2, E_MESSAGE_ERROR )->save('PREF_01'); - * -*/ - -if (!defined('e107_INIT')) -{ - exit; -} - -define('LOG_MESSAGE_NODISPLAY', 'nodisplay'); - -/** - * Admin logging class. - * - * @package e107 - * @subpackage e107_handlers - * @version $Id$; - * @author e107steved - */ -class e_admin_log -{ - - /** - * Contains default class options, plus any that are overidden by the constructor - * - * @var array - */ - protected $_options = array('log_level'=>2, 'backtrace'=>false, ); - - protected $rldb = NULL; // Database used by logging routine - - - - protected $logFile = null; - /** - * Log messages - * @var array - */ - protected $_messages; - - - protected $_allMessages; // similar to $_messages except it is never flushed. - - - protected $_current_plugin = null; - - - /** - * Constructor. Sets up constants and overwrites default options where set. - * - * @param array $options - * @return none - */ - public function __construct($options = array()) - { - if(!empty($options)) - { - foreach ($options as $key=>$val) - { - $this->_options[$key] = $val; - } - } - - define("E_LOG_INFORMATIVE", 0); // Minimal Log Level, including really minor stuff - define("E_LOG_NOTICE", 1); // More important than informative, but less important than notice - define("E_LOG_WARNING", 2); // Not anything serious, but important information - define("E_LOG_FATAL", 3); // An event so bad your site ceased execution. - define("E_LOG_PLUGIN", 4); // Plugin information - - // Logging actions - define("LOG_TO_ADMIN", 1); - define("LOG_TO_AUDIT", 2); - define("LOG_TO_ROLLING", 4); - - // User audit logging (intentionally start at 10 - stick to 2 digits) - // The last two digits must match that for the corresponding log message - define('USER_AUDIT_ADMIN', 10); // User data changed by admin - define('USER_AUDIT_SIGNUP', 11); // User signed up - define('USER_AUDIT_EMAILACK', 12); // User responded to registration email - define('USER_AUDIT_LOGIN', 13); // User logged in - define('USER_AUDIT_LOGOUT', 14); // User logged out - define('USER_AUDIT_NEW_DN', 15); // User changed display name - define('USER_AUDIT_NEW_PW', 16); // User changed password - define('USER_AUDIT_NEW_EML', 17); // User changed email - define('USER_AUDIT_PW_RES', 18); // Password reset/resent activation email - define('USER_AUDIT_NEW_SET', 19); // User changed other settings - define('USER_AUDIT_ADD_ADMIN', 20); // User added by admin - define('USER_AUDIT_MAIL_BOUNCE', 21); // User mail bounce - define('USER_AUDIT_BANNED', 22); // User banned - define('USER_AUDIT_BOUNCE_RESET', 23); // User bounce reset - define('USER_AUDIT_TEMP_ACCOUNT', 24); // User temporary account - - // Init E_MESSAGE_* constants if not already done - // e107::getMessage(); - just include, message handler is creating session in construct - // it breaks stuff (see class2 - language detection and comments) - require_once(e_HANDLER.'message_handler.php'); - $this->_messages = array(); - $this->_allMessages = array(); - - } - - /** - * @DEPRECATED - * BC Alias of add(); - */ - public function log_event($event_title, $event_detail, $event_type = E_LOG_INFORMATIVE , $event_code = '') - { - return $this->add($event_title, $event_detail, $event_type, $event_code); - } - - - /** - * Save all logs in the queue to the database and render any unhidden messages with the message handler. - * @see alias flushMessages() method below. - * @param string $logTitle - title for log entry eg. 'PREF_01' - * @param int $logImportance [optional] default E_LOG_INFORMATIVE - passed directly to admin log - * @param string $logEventCode [optional] - passed directly to admin log - * @param string $mstack [optional] message stack passed to message handler - * @param int LOG_TO_ADMIN|LOG_TO_ROLLING|LOG_TO_AUDIT - * @return \e_admin_log - */ - public function save($logTitle, $logImportance = E_LOG_INFORMATIVE, $logEventCode = '', $mstack = false, $target = LOG_TO_ADMIN) - { - return $this->flushMessages($logTitle, $logImportance, $logEventCode, $mstack, $target); - } - - - - - /** - * Add and Save an event into the admin, rolling or user log. - * @param string $event_title - * @param mixed $event_details - * @param integer $event_type [optional] Log level eg. E_LOG_INFORMATIVE, E_LOG_NOTICE, E_LOG_WARNING, E_LOG_FATAL - * @param string $event_code [optional] - eg. 'BOUNCE' - * @param integer $target [optional] LOG_TO_ADMIN, LOG_TO_AUDIT, LOG_TO_ROLLING - * @param array $user - user to attribute the log to. array('user_id'=>2, 'user_name'=>'whoever'); - * @return e_admin_log - * - * Alternative admin log entry point - compatible with legacy calls, and a bit simpler to use than the generic entry point. - * ($eventcode has been added - give it a reference to identify the source module, such as 'NEWS_12' or 'ECAL_03') - * We also log everything (unlike 0.7, where admin log and debug stuff were all mixed up together) - * - * For multi-lingual logging (where the event title is shown in the language of the current user), LAN defines may be used in the title - * - * For generic calls, leave $event_code as empty, and specify a constant string STRING_nn of less than 10 characters for the event title - * Typically the 'STRING' part of the name defines the area originating the log event, and the 'nn' is a numeric code - * This is stored as 'LAN_AL_STRING_NN', and must be defined in a language file which is loaded during log display. - * - - */ - public function add($event_title, $event_detail, $event_type = E_LOG_INFORMATIVE , $event_code = '', $target = LOG_TO_ADMIN, $userData=null ) - { - if ($event_code == '') - { - if (strlen($event_title) <= 12) - { // Assume the title is actually a reference to the event - $event_code = $event_title; - $event_title = 'LAN_AL_'.$event_title; - } - else - { - $event_code = 'ADMIN'; - } - } - //SecretR - now supports DB array as event_detail (see e.g. db::db_Insert()) - if (is_array($event_detail)) - { - // handled inside e_log_event(); - - /* - $tmp = array(); - if (isset($event_detail['data'])) - { - $event_detail = $event_detail['data']; - } - foreach ($event_detail as $k => $v) - { - $tmp[] = $k.'=>'.$v; - } - $event_detail = implode("[!br!]\n", $tmp); - unset($tmp); - */ - - } - else - { - // auto-format long details - TODO - shrink details on administration log page, expand/show in DHTML window full details. - $event_detail = str_replace("\n", "[!br!]", $event_detail); - } - - if ($this->_options['backtrace'] == true) - { - $event_detail .= "\n\n".debug_backtrace(false); - } - - - $this->e_log_event($event_type, -1, $event_code, $event_title, $event_detail, FALSE, $target, $userData); - - return $this; - } - - /** - Generic log entry point - ----------------------- - Example call: (Deliberately pick separators that shouldn't be in file names) - e_log_event(E_LOG_NOTICE,__FILE__."|".__FUNCTION__."@".__LINE__,"ECODE","Event Title","explanatory message",FALSE,LOG_TO_ADMIN); - or: - e_log_event(E_LOG_NOTICE,debug_backtrace(),"ECODE","Event Title","explanatory message",TRUE,LOG_TO_ROLLING); - * - * @param int $importance - importance of event - 0..4 or so - * @param mixed $source_call - either: string identifying calling file/routine - * or: a number 0..9 identifying info to log from debug_backtrace() - * or: empty string, in which case first entry from debug_backtrace() logged - * or: an array, assumed to be from passing debug_backtrace() as a parameter, in which case relevant - * information is extracted and the argument list from the first entry logged - * or: -1, in which case no information logged - * @param string $eventcode - abbreviation listing event type - * @param string $event_title - title of event - pass standard 'LAN_ERROR_nn' defines to allow language translation - * @param string $explain - detail of event - * @param bool $finished - if TRUE, aborts execution - * @param int $target_logs - flags indicating which logs to update - if entry to be posted in several logs, add (or 'OR') their defines: - * LOG_TO_ADMIN - admin log - * LOG_TO_AUDIT - audit log - * LOG_TO_ROLLING - rolling log - * @param array $userData - attribute user to log entry. array('user_id'=>2, 'user_name'=>'whatever'); - * @return none - - * @todo - check microtime() call - * @deprecated - use add() method instead. - */ - public function e_log_event($importance, $source_call, $eventcode = "GEN", $event_title = "Untitled", $explain = "", $finished = FALSE, $target_logs = LOG_TO_AUDIT, $userData=null ) - { - $e107 = e107::getInstance(); - $pref = e107::getPref(); - $tp = e107::getParser(); - - list($time_usec, $time_sec) = explode(" ", microtime(FALSE)); // Log event time immediately to minimise uncertainty - $time_usec = $time_usec * 1000000; - - if ($this->rldb == NULL) - $this->rldb = e107::getDb('adminlog'); // Better use our own db - don't know what else is going on - - if (is_bool($target_logs)) - { // Handle the legacy stuff for now - some old code used a boolean to select admin or rolling logs - $target_logs = $target_logs ? LOG_TO_ADMIN : LOG_TO_ROLLING; - } - - //--------------------------------------- - // Calculations common to all logs - //--------------------------------------- - - $userid = deftrue('USER') ? USERID : 0; - $userstring = deftrue('USER') ? USERNAME : 'LAN_ANONYMOUS'; - $userIP = e107::getIPHandler()->getIP(FALSE); - - if(!empty($userData['user_id'])) - { - $userid = $userData['user_id']; - } - - if(!empty($userData['user_name'])) - { - $userstring = $userData['user_name']; - } - - if(!empty($userData['user_ip'])) - { - $userIP = $userData['user_ip']; - } - - $importance = $tp->toDB($importance, true, false, 'no_html'); - $eventcode = $tp->toDB($eventcode, true, false, 'no_html'); - - if (is_array($explain)) - { - /* - $line = ''; - $spacer = ''; - foreach ($explain as $k=>$v) - { - $line .= $spacer.$k.'=>'.$v; - $spacer = '[!br!]'; - } - $explain = $line; - unset($line); - */ - $explain = str_replace("\n",'[!br!]',print_r($explain,true)); - - } - - - $explain = e107::getDb()->escape($tp->toDB($explain, true, false, 'no_html')); - $event_title = $tp->toDB($event_title, true, false, 'no_html'); - - //--------------------------------------- - // Admin Log - //--------------------------------------- - if ($target_logs & LOG_TO_ADMIN) // Admin log - assume all fields valid - { - // $qry = " null, ".intval($time_sec).','.intval($time_usec).", '{$importance}', '{$eventcode}', {$userid}, '{$userIP}', '{$event_title}', '{$explain}' "; - - $adminLogInsert = array( - 'dblog_id' => null, - 'dblog_type' => $importance, - 'dblog_eventcode' => $eventcode, - 'dblog_datestamp' => time(), - 'dblog_microtime' => intval($time_usec), - 'dblog_user_id' => $userid, - 'dblog_ip' => $userIP, - 'dblog_title' => $event_title, - 'dblog_remarks' => $explain - ); - - $this->rldb->insert("admin_log", $adminLogInsert); - } - - //--------------------------------------- - // Audit Log - //--------------------------------------- - // Add in audit log here - - //--------------------------------------- - // Rolling Log - //--------------------------------------- - if (($target_logs & LOG_TO_ROLLING) && vartrue($pref['roll_log_active'])) - { // Rolling log - - // Process source_call info - //--------------------------------------- - if (is_numeric($source_call) && ($source_call >= 0)) - { - $back_count = 1; - $i = 0; - if (is_numeric($source_call) || ($source_call == '')) - { - $back_count = $source_call + 1; - $source_call = debug_backtrace(); - $i = 1; // Don't want to print the entry parameters to this function - we know all that! - } - } - - if (is_array($source_call)) - { // Print the debug_backtrace() array - while ($i < $back_count) - { - $source_call[$i]['file'] = $e107->fix_windows_paths($source_call[$i]['file']); // Needed for Windoze hosts. - $source_call[$i]['file'] = str_replace($e107->file_path, "", $source_call[$i]['file']); // We really just want a e107 root-relative path. Strip out the root bit - $tmp = $source_call[$i]['file']."|".$source_call[$i]['class'].$source_call[$i]['type'].$source_call[$i]['function']."@".$source_call[$i]['line']; - foreach ($source_call[$i]['args'] as $k=>$v) - { // Add in the arguments - $explain .= "[!br!]".$k."=".$v; - } - $i++; - if ($i < $back_count) - $explain .= "[!br!]-------------------"; - if (!isset($tmp1)) - $tmp1 = $tmp; // Pick off the immediate caller as the source - } - if (isset($tmp1)) $source_call = $tmp1; - else $source_call = 'Root level'; - } - else - { - $source_call = $e107->fix_windows_paths($source_call); // Needed for Windoze hosts. - $source_call = str_replace($e107->file_path, "", $source_call); // We really just want a e107 root-relative path. Strip out the root bit - $source_call = $tp->toDB($source_call, true, false, 'no_html'); - } - // else $source_call is a string - - // Save new rolling log record - $this->rldb->insert("dblog", "0, ".intval($time_sec).', '.intval($time_usec).", '{$importance}', '{$eventcode}', {$userid}, '{$userstring}', '{$userIP}', '{$source_call}', '{$event_title}', '{$explain}' "); - - // Now delete any old stuff - if(!empty($pref['roll_log_days'])) - { - $days = intval($pref['roll_log_days']); - $this->rldb->delete("dblog", "dblog_datestamp < '".intval(time() - ($days * 86400))."' "); - } - } - - if ($finished) - exit; // Optional abort for all logs - } - - public function setCurrentPlugin($plugdir) - { - $this->_current_plugin = $plugdir; - - return $this; - } - - /**-------------------------------------- - * USER AUDIT ENTRY - *-------------------------------------- - * Log user-related events - * @param int $event_code is a defined constant (see above) which specifies the event - * @param array $event_data is an array of data fields whose keys and values are logged (usually user data, but doesn't have to be - can add messages here) - * @param int $id - * @param string $u_name - * both $id and $u_name are left blank except for admin edits and user login, where they specify the id and login name of the 'target' user - * - * @return bool - */ - function user_audit($event_type, $event_data, $id = '', $u_name = '') - { - list($time_usec, $time_sec) = explode(" ", microtime()); // Log event time immediately to minimise uncertainty - - $time_usec = $time_usec * 1000000; - - if(!is_numeric($event_type)) - { - $title = "User Audit Event-Type Failure: "; - $title .= (string) $event_type; - $debug = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,4); - $debug[0] = e_REQUEST_URI; - - $this->e_log_event(4, $debug[1]['file']."|".$debug[1]['function']."@".$debug[1]['line'], "USERAUDIT", $title, $debug, FALSE); - return false; - } - - // See whether we should log this - $user_logging_opts = e107::getConfig()->get('user_audit_opts'); - - if (!isset($user_logging_opts[$event_type])) // Finished if not set to log this event type - { - return false; - } - - if(empty($event_data)) - { - $backt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,4); - $event_data = $backt; - } - - - if($this->rldb == null) - { - $this->rldb = e107::getDb('rldb'); // Better use our own db - don't know what else is going on - } - - if(!empty($id)) - { - $userid = $id; - } - else - { - $userid = (USER === true) ? USERID : 0; - } - - if(!empty($u_name)) - { - $userstring = $u_name; - } - else - { - $userstring = (USER === true ? USERNAME : "LAN_ANONYMOUS"); - } - - $userIP = e107::getIPHandler()->getIP(false); - - $eventcode = 'USER_'.$event_type; - - $title = 'LAN_AUDIT_LOG_0'.$event_type; // This creates a string which will be displayed as a constant - - $insertQry = array( - 'dblog_id' => 0, - 'dblog_datestamp' => intval($time_sec), - 'dblog_microtime' => intval($time_usec), - 'dblog_eventcode' => $eventcode, - 'dblog_user_id' => $userid, - 'dblog_user_name' => $userstring, - 'dblog_ip' => $userIP, - 'dblog_title' => $title, - 'dblog_remarks' => print_r($event_data,true), - ); - - if($this->rldb->insert("audit_log", $insertQry)) - { - return true; - } - - return false; - } - - - /* Legacy function probably not needed - function get_log_events($count = 15, $offset) - { - global $sql; - $count = intval($count); - return "Not implemented yet"; - } - */ - - - - /** - * Removes all events older than $days, or truncates the table if $days == false - * - * @param integer|false $days - * @return void - */ - public function purge_log_events($days) - { - global $sql; - if ($days == false) - { // $days is false, so truncate the log table - $sql->gen("TRUNCATE TABLE #dblog "); - } - else - { // $days is set, so remove all entries older than that. - $days = intval($days); - $mintime = $days * 24 * 60 * 60; - $time = time() - $mintime; - $sql->db_Delete("dblog", "WHERE `dblog_datestamp` < {$time}", true); - } - } - - //-------------------------------------- - // HELPER ROUTINES - //-------------------------------------- - /** - * Generic routine to log changes to an array. Only elements in $new are checked - * - * @param array $new - most recent data being saved - * @param array $old existing data - array is updated with changes, but not saved anywhere - * @param string $event - LAN define or string used as title in log - * - * @return bool true if changes found and logged, false otherwise. - */ - function logArrayDiffs($new, $old, $event, $logNow = true) - { - // $changes = array(); - - $changes = array_diff_recursive($new,$old); - - if (count($changes)) - { - if($logNow) - { - $this->add($event, print_r($changes,true), E_LOG_INFORMATIVE, ''); - } - else - { - $this->logMessage($changes, LOG_MESSAGE_NODISPLAY, E_MESSAGE_INFO); - } - - return TRUE; - } - - return FALSE; - } - - - /** - * Logs an entry with all the data from an array, one field per line. - * @deprecated - * @param string $event - LAN define or string used as title in log - * @param array $target - data to be logged - * @param string $extra - if non-empty, it goes on the first line. - * @param array $niceNames - Normally data is logged in the format keyname=>value, one per line. - * If the $niceName array exists and has a definition, the 'nice Name' is displayed instead of the key name - * - * @return none - */ - public function logArrayAll($event, $target, $extra = '', $niceNames = NULL) - { - - if($extra == '' && $niceNames == null) - { - return $this->add($event, $target, E_LOG_INFORMATIVE, ''); // supports arrays - - } - - - $logString = ''; - if ($extra) - { - $logString = $extra.'[!br!]'; - } - $spacer = ''; - $checkNice = ($niceNames != NULL) && is_array($niceNames); - foreach ($target as $k=>$v) - { - if ($checkNice && isset($niceNames[$k]['niceName'])) - { - $logString .= $spacer.$niceNames[$k]['niceName'].'=>'.$v; - } - else - { - $logString .= $spacer.$k.'=>'.$v; - } - $spacer = '[!br!]'; - } - $this->add($event, $logString, E_LOG_INFORMATIVE, ''); - } - - /** - * The next two routines accept and buffers messages which are destined for both admin log and message handler - */ - - /** - * Add a message to the queue - * - * @param string|array $text - the message text for logging/display - * @param int $type - the 'importance' of the message. E_MESSAGE_SUCCESS|E_MESSAGE_ERROR|E_MESSAGE_INFO|E_MESSAGE_DEBUG|E_MESSAGE_NODISPLAY - * (Values as used in message handler, apart from the last, which causes the message to not be passed to the message handler - * @param boolean|int $logLevel - TRUE to give same importance as for message display. FALSE to not log. - * one of the values specified for $mesLevel to determine the prefix attached to the log message - * @param boolean $session add session message - * - * @return e_admin_log - */ - public function logMessage($text, $type = '', $logLevel = TRUE, $session = FALSE) - { - - if(is_array($text)) - { - $text = print_r($text,true); - } - elseif(empty($text)) - { - $bt = debug_backtrace(true); - e107::getMessage()->addDebug("Log Message was empty: ".print_a($bt[1],true)); - return $this; // changing to text will break chained methods. - } - - if(!$type) $type = E_MESSAGE_INFO; - if($logLevel === TRUE) $logLevel = $type; - - $logArray = array('message' => $text, 'dislevel' => $type, 'loglevel' => $logLevel, 'session' => $session, 'time'=>time()); - - $this->_messages[] = $logArray; - $this->_allMessages[] = $logArray; - - return $this; - } - - - - /** - * @DEPRECATED - * BC Alias for addSuccess(); - */ - public function logSuccess($text, $message = true, $session = false) - { - return $this->addSuccess($text,$message,$session); - } - - - - /** - * @DEPRECATED - * BC Alias for addError(); - */ - public function logError($text, $message = true, $session = false) - { - return $this->addError($text,$message,$session); - } - - - /** - * Add a success message to the log queue - * - * @param string|array $text - * @param boolean $message if true - register with eMessage handler - * @param boolean $session add session message - * @return e_admin_log - */ - public function addSuccess($text, $message = true, $session = false) - { - return $this->logMessage($text, ($message ? E_MESSAGE_SUCCESS : LOG_MESSAGE_NODISPLAY), E_MESSAGE_SUCCESS, $session); - } - - - /** - * Add an error message to the log queue - * - * @param string $text - * @param boolean $message if true (default) - register with eMessage handler, set to false to hide. - * @param boolean $session add session message - * @return e_admin_log - */ - public function addError($text, $message = true, $session = false) - { - return $this->logMessage($text, ($message ? E_MESSAGE_ERROR : LOG_MESSAGE_NODISPLAY), E_MESSAGE_ERROR, $session); - } - - - /** - * Add an Debug message to the log queue - * - * @param string $text - * @param boolean $message if true (default) - register with eMessage handler, set to false to hide . - * @param boolean $session add session message - * @return e_admin_log - */ - public function addDebug($text, $message = true, $session = false) - { - return $this->logMessage($text, ($message ? E_MESSAGE_DEBUG : LOG_MESSAGE_NODISPLAY), E_MESSAGE_DEBUG, $session); - } - - - /** - * Add an Warning message to the log queue - * - * @param string $text - * @param boolean $message if true (default) - register with eMessage handler, set to false to hide. - * @param boolean $session add session message - * @return e_admin_log - */ - public function addWarning($text, $message = true, $session = false) - { - return $this->logMessage($text, ($message ? E_MESSAGE_WARNING : LOG_MESSAGE_NODISPLAY), E_MESSAGE_WARNING, $session); - } - - - /** - * Add an array to the log queue - * @param $array - * @param $oldArray (optional) - when included, only the changes between the arrays is saved. - * @param $type (optional) default: LOG_MESSAGE_NODISPLAY. or E_MESSAGE_WARNING, E_MESSAGE_DEBUG, E_MESSAGE_SUCCESS - */ - public function addArray($array, $oldArray= null, $type = LOG_MESSAGE_NODISPLAY , $session = false) - { - if(is_array($oldArray)) - { - $text = array_diff_recursive($array,$oldArray); // Located in core_functions.php - if(count($text) < 1) - { - $text = "No differences found"; - } - - } - else - { - $text = $array; - } - - return $this->logMessage($text, $type, $type, $session); - } - - /** - * Empty the messages - pass to both admin log and message handler - * - * @param string $logTitle - title for log entry - * @param int $logImportance - passed directly to admin log - * @param string $logEventCode - passed directly to admin log - * @param string $mstack [optional] message stack passed to message handler - * @return e_admin_log - */ - public function flushMessages($logTitle, $logImportance = E_LOG_INFORMATIVE, $logEventCode = '', $mstack = false, $target =LOG_TO_ADMIN) - { - $mes = e107::getMessage(); - - $resultTypes = array(E_MESSAGE_SUCCESS => 'Success', E_MESSAGE_ERROR => 'Fail'); // Add LANS here. Could add other codes - $separator = ''; - $logString = ''; - foreach ($this->_messages as $m) - { - if ($m['loglevel'] !== FALSE) - { - $logString .= $separator; - if ($m['loglevel'] == LOG_MESSAGE_NODISPLAY) { $logString .= ' '; } // Indent supplementary messages - // Not sure about next line - might want to log the
as text, rather than it forcing a newline - $logString .= strip_tags(str_replace(array('
', '
', '
'), '[!br!]', $m['message'])); - if (isset($resultTypes[$m['loglevel']])) - { - $logString .= ' - '.$resultTypes[$m['loglevel']]; - } - $separator = '[!br!]'; - } - if ($m['dislevel'] != LOG_MESSAGE_NODISPLAY) - { - if($mstack) - { - $mes->addStack($m['message'], $mstack, $m['dislevel'], $m['session']); - // move to main stack OUTSIDE if needed - } - else $mes->add($m['message'], $m['dislevel'], $m['session']); - } - } - $this->add($logTitle, $logString, $logImportance, $logEventCode, $target); - $this->_messages = array(); // Clear the memory for reuse - - return $this; - } - - - - - - /** - * Clear all messages in 'memory'. - */ - public function clear() - { - $this->_messages = array(); - - return $this; - } - - - /** - * Save Message stack to File. - */ - private function saveToFile($logTitle='', $append=false, $opts = array()) - { - if($this->logFile == null) - { - return; - } - - if(count($this->_allMessages)) - { - $head = " e107 CMS Log file : ".$logTitle." ".date('Y-m-d_H-i-s')."\n"; - $head .= "-------------------------------------------------------------------------------------------\n\n"; - } - else - { - return; - } - - $text = ''; - - foreach($this->_allMessages as $m) - { - $text .= date('Y-m-d H:i:s', $m['time'])." \t".str_pad($m['loglevel'],10," ",STR_PAD_RIGHT)."\t".strip_tags($m['message'])."\n"; - } - - $date = ($append == true) ? date('Y-m-d') : date('Y-m-d_H-i-s').'_'.crc32($text); - - - - $dir = e_LOG; - - if(empty($this->_current_plugin)) - { - $this->_current_plugin = deftrue('e_CURRENT_PLUGIN'); - } - - if(!empty($this->_current_plugin)) // If it's a plugin, create a subfolder. - { - $dir = e_LOG.$this->_current_plugin."/"; - - if(!is_dir($dir)) - { - mkdir($dir,0755); - } - } - - $fileName = $dir.$date."_".$this->logFile.".log"; - - if(!empty($opts['filename'])) - { - $fileName = $dir.basename($opts['filename']); - } - - if($append == true) - { - $app = FILE_APPEND; - if(!file_exists($fileName)) - { - $text = $head . $text; - } - } - else - { - $app = null; - $text = $head . $text; - } - - if(file_put_contents($fileName, $text, $app)) - { - $this->_allMessages = array(); - $this->_current_plugin = null; - return $this->logFile; - } - elseif(getperms('0') && E107_DEBUG_LEVEL > 0) - { - e107::getMessage()->addDebug("Couldn't Save to Log File: ".$fileName); - } - - $this->_current_plugin = null; - - return false; - } - - - - - /** - * Set and save accumulated log to a file. - * Use addDebug(), addError() or addSuccess() prior to executing. - * @param string name without the extension. (ie. date prefix and .log suffix will be added automatically) - * @param string Title for use inside the Log file - * @param boolean true = append to file, false = new file each save. - */ - public function toFile($name, $logTitle='',$append=false, $opts=array()) - { - - $this->logFile = $name; - $file = $this->saveToFile($logTitle,$append,$opts); - - $this->logFile = null; - return $file; - } - - -} +addSuccess("Successfully executed")->save('PREF_01'); + * @example Log Only: e107::getAdminLog()->addSuccess("Successfully executed",false)->save('PREF_01'); + * @example Log Array Diff: e107::getAdminLog()->addArray($array1, $array2)->save('PREF_01'); + * @example Log Array Diff and Add to Message Handler: e107::getAdminLog()->addArray($array1, $array2, E_MESSAGE_ERROR )->save('PREF_01'); + * +*/ + +if (!defined('e107_INIT')) +{ + exit; +} + +define('LOG_MESSAGE_NODISPLAY', 'nodisplay'); + +/** + * Admin logging class. + * + * @package e107 + * @subpackage e107_handlers + * @version $Id$; + * @author e107steved + */ +class e_admin_log +{ + + /** + * Contains default class options, plus any that are overidden by the constructor + * + * @var array + */ + protected $_options = array('log_level'=>2, 'backtrace'=>false, ); + + protected $rldb = NULL; // Database used by logging routine + + + + protected $logFile = null; + /** + * Log messages + * @var array + */ + protected $_messages; + + + protected $_allMessages; // similar to $_messages except it is never flushed. + + + protected $_current_plugin = null; + + + /** + * Constructor. Sets up constants and overwrites default options where set. + * + * @param array $options + * @return none + */ + public function __construct($options = array()) + { + if(!empty($options)) + { + foreach ($options as $key=>$val) + { + $this->_options[$key] = $val; + } + } + + define("E_LOG_INFORMATIVE", 0); // Minimal Log Level, including really minor stuff + define("E_LOG_NOTICE", 1); // More important than informative, but less important than notice + define("E_LOG_WARNING", 2); // Not anything serious, but important information + define("E_LOG_FATAL", 3); // An event so bad your site ceased execution. + define("E_LOG_PLUGIN", 4); // Plugin information + + // Logging actions + define("LOG_TO_ADMIN", 1); + define("LOG_TO_AUDIT", 2); + define("LOG_TO_ROLLING", 4); + + // User audit logging (intentionally start at 10 - stick to 2 digits) + // The last two digits must match that for the corresponding log message + define('USER_AUDIT_ADMIN', 10); // User data changed by admin + define('USER_AUDIT_SIGNUP', 11); // User signed up + define('USER_AUDIT_EMAILACK', 12); // User responded to registration email + define('USER_AUDIT_LOGIN', 13); // User logged in + define('USER_AUDIT_LOGOUT', 14); // User logged out + define('USER_AUDIT_NEW_DN', 15); // User changed display name + define('USER_AUDIT_NEW_PW', 16); // User changed password + define('USER_AUDIT_NEW_EML', 17); // User changed email + define('USER_AUDIT_PW_RES', 18); // Password reset/resent activation email + define('USER_AUDIT_NEW_SET', 19); // User changed other settings + define('USER_AUDIT_ADD_ADMIN', 20); // User added by admin + define('USER_AUDIT_MAIL_BOUNCE', 21); // User mail bounce + define('USER_AUDIT_BANNED', 22); // User banned + define('USER_AUDIT_BOUNCE_RESET', 23); // User bounce reset + define('USER_AUDIT_TEMP_ACCOUNT', 24); // User temporary account + + // Init E_MESSAGE_* constants if not already done + // e107::getMessage(); - just include, message handler is creating session in construct + // it breaks stuff (see class2 - language detection and comments) + require_once(e_HANDLER.'message_handler.php'); + $this->_messages = array(); + $this->_allMessages = array(); + + } + + /** + * @DEPRECATED + * BC Alias of add(); + */ + public function log_event($event_title, $event_detail, $event_type = E_LOG_INFORMATIVE , $event_code = '') + { + return $this->add($event_title, $event_detail, $event_type, $event_code); + } + + + /** + * Save all logs in the queue to the database and render any unhidden messages with the message handler. + * @see alias flushMessages() method below. + * @param string $logTitle - title for log entry eg. 'PREF_01' + * @param int $logImportance [optional] default E_LOG_INFORMATIVE - passed directly to admin log + * @param string $logEventCode [optional] - passed directly to admin log + * @param string $mstack [optional] message stack passed to message handler + * @param int LOG_TO_ADMIN|LOG_TO_ROLLING|LOG_TO_AUDIT + * @return \e_admin_log + */ + public function save($logTitle, $logImportance = E_LOG_INFORMATIVE, $logEventCode = '', $mstack = false, $target = LOG_TO_ADMIN) + { + return $this->flushMessages($logTitle, $logImportance, $logEventCode, $mstack, $target); + } + + + + + /** + * Add and Save an event into the admin, rolling or user log. + * @param string $event_title + * @param mixed $event_details + * @param integer $event_type [optional] Log level eg. E_LOG_INFORMATIVE, E_LOG_NOTICE, E_LOG_WARNING, E_LOG_FATAL + * @param string $event_code [optional] - eg. 'BOUNCE' + * @param integer $target [optional] LOG_TO_ADMIN, LOG_TO_AUDIT, LOG_TO_ROLLING + * @param array $user - user to attribute the log to. array('user_id'=>2, 'user_name'=>'whoever'); + * @return e_admin_log + * + * Alternative admin log entry point - compatible with legacy calls, and a bit simpler to use than the generic entry point. + * ($eventcode has been added - give it a reference to identify the source module, such as 'NEWS_12' or 'ECAL_03') + * We also log everything (unlike 0.7, where admin log and debug stuff were all mixed up together) + * + * For multi-lingual logging (where the event title is shown in the language of the current user), LAN defines may be used in the title + * + * For generic calls, leave $event_code as empty, and specify a constant string STRING_nn of less than 10 characters for the event title + * Typically the 'STRING' part of the name defines the area originating the log event, and the 'nn' is a numeric code + * This is stored as 'LAN_AL_STRING_NN', and must be defined in a language file which is loaded during log display. + * + + */ + public function add($event_title, $event_detail, $event_type = E_LOG_INFORMATIVE , $event_code = '', $target = LOG_TO_ADMIN, $userData=null ) + { + if ($event_code == '') + { + if (strlen($event_title) <= 12) + { // Assume the title is actually a reference to the event + $event_code = $event_title; + $event_title = 'LAN_AL_'.$event_title; + } + else + { + $event_code = 'ADMIN'; + } + } + //SecretR - now supports DB array as event_detail (see e.g. db::db_Insert()) + if (is_array($event_detail)) + { + // handled inside e_log_event(); + + /* + $tmp = array(); + if (isset($event_detail['data'])) + { + $event_detail = $event_detail['data']; + } + foreach ($event_detail as $k => $v) + { + $tmp[] = $k.'=>'.$v; + } + $event_detail = implode("[!br!]\n", $tmp); + unset($tmp); + */ + + } + else + { + // auto-format long details - TODO - shrink details on administration log page, expand/show in DHTML window full details. + $event_detail = str_replace("\n", "[!br!]", $event_detail); + } + + if ($this->_options['backtrace'] == true) + { + $event_detail .= "\n\n".debug_backtrace(false); + } + + + $this->e_log_event($event_type, -1, $event_code, $event_title, $event_detail, FALSE, $target, $userData); + + return $this; + } + + /** + Generic log entry point + ----------------------- + Example call: (Deliberately pick separators that shouldn't be in file names) + e_log_event(E_LOG_NOTICE,__FILE__."|".__FUNCTION__."@".__LINE__,"ECODE","Event Title","explanatory message",FALSE,LOG_TO_ADMIN); + or: + e_log_event(E_LOG_NOTICE,debug_backtrace(),"ECODE","Event Title","explanatory message",TRUE,LOG_TO_ROLLING); + * + * @param int $importance - importance of event - 0..4 or so + * @param mixed $source_call - either: string identifying calling file/routine + * or: a number 0..9 identifying info to log from debug_backtrace() + * or: empty string, in which case first entry from debug_backtrace() logged + * or: an array, assumed to be from passing debug_backtrace() as a parameter, in which case relevant + * information is extracted and the argument list from the first entry logged + * or: -1, in which case no information logged + * @param string $eventcode - abbreviation listing event type + * @param string $event_title - title of event - pass standard 'LAN_ERROR_nn' defines to allow language translation + * @param string $explain - detail of event + * @param bool $finished - if TRUE, aborts execution + * @param int $target_logs - flags indicating which logs to update - if entry to be posted in several logs, add (or 'OR') their defines: + * LOG_TO_ADMIN - admin log + * LOG_TO_AUDIT - audit log + * LOG_TO_ROLLING - rolling log + * @param array $userData - attribute user to log entry. array('user_id'=>2, 'user_name'=>'whatever'); + * @return none + + * @todo - check microtime() call + * @deprecated - use add() method instead. + */ + public function e_log_event($importance, $source_call, $eventcode = "GEN", $event_title = "Untitled", $explain = "", $finished = FALSE, $target_logs = LOG_TO_AUDIT, $userData=null ) + { + $e107 = e107::getInstance(); + $pref = e107::getPref(); + $tp = e107::getParser(); + + list($time_usec, $time_sec) = explode(" ", microtime(FALSE)); // Log event time immediately to minimise uncertainty + $time_usec = $time_usec * 1000000; + + if ($this->rldb == NULL) + $this->rldb = e107::getDb('adminlog'); // Better use our own db - don't know what else is going on + + if (is_bool($target_logs)) + { // Handle the legacy stuff for now - some old code used a boolean to select admin or rolling logs + $target_logs = $target_logs ? LOG_TO_ADMIN : LOG_TO_ROLLING; + } + + //--------------------------------------- + // Calculations common to all logs + //--------------------------------------- + + $userid = deftrue('USER') ? USERID : 0; + $userstring = deftrue('USER') ? USERNAME : 'LAN_ANONYMOUS'; + $userIP = e107::getIPHandler()->getIP(FALSE); + + if(!empty($userData['user_id'])) + { + $userid = $userData['user_id']; + } + + if(!empty($userData['user_name'])) + { + $userstring = $userData['user_name']; + } + + if(!empty($userData['user_ip'])) + { + $userIP = $userData['user_ip']; + } + + $importance = $tp->toDB($importance, true, false, 'no_html'); + $eventcode = $tp->toDB($eventcode, true, false, 'no_html'); + + if (is_array($explain)) + { + /* + $line = ''; + $spacer = ''; + foreach ($explain as $k=>$v) + { + $line .= $spacer.$k.'=>'.$v; + $spacer = '[!br!]'; + } + $explain = $line; + unset($line); + */ + $explain = str_replace("\n",'[!br!]',print_r($explain,true)); + + } + + + $explain = e107::getDb()->escape($tp->toDB($explain, true, false, 'no_html')); + $event_title = $tp->toDB($event_title, true, false, 'no_html'); + + //--------------------------------------- + // Admin Log + //--------------------------------------- + if ($target_logs & LOG_TO_ADMIN) // Admin log - assume all fields valid + { + // $qry = " null, ".intval($time_sec).','.intval($time_usec).", '{$importance}', '{$eventcode}', {$userid}, '{$userIP}', '{$event_title}', '{$explain}' "; + + $adminLogInsert = array( + 'dblog_id' => null, + 'dblog_type' => $importance, + 'dblog_eventcode' => $eventcode, + 'dblog_datestamp' => time(), + 'dblog_microtime' => intval($time_usec), + 'dblog_user_id' => $userid, + 'dblog_ip' => $userIP, + 'dblog_title' => $event_title, + 'dblog_remarks' => $explain + ); + + $this->rldb->insert("admin_log", $adminLogInsert); + } + + //--------------------------------------- + // Audit Log + //--------------------------------------- + // Add in audit log here + + //--------------------------------------- + // Rolling Log + //--------------------------------------- + if (($target_logs & LOG_TO_ROLLING) && vartrue($pref['roll_log_active'])) + { // Rolling log + + // Process source_call info + //--------------------------------------- + if (is_numeric($source_call) && ($source_call >= 0)) + { + $back_count = 1; + $i = 0; + if (is_numeric($source_call) || ($source_call == '')) + { + $back_count = $source_call + 1; + $source_call = debug_backtrace(); + $i = 1; // Don't want to print the entry parameters to this function - we know all that! + } + } + + if (is_array($source_call)) + { // Print the debug_backtrace() array + while ($i < $back_count) + { + $source_call[$i]['file'] = $e107->fix_windows_paths($source_call[$i]['file']); // Needed for Windoze hosts. + $source_call[$i]['file'] = str_replace($e107->file_path, "", $source_call[$i]['file']); // We really just want a e107 root-relative path. Strip out the root bit + $tmp = $source_call[$i]['file']."|".$source_call[$i]['class'].$source_call[$i]['type'].$source_call[$i]['function']."@".$source_call[$i]['line']; + foreach ($source_call[$i]['args'] as $k=>$v) + { // Add in the arguments + $explain .= "[!br!]".$k."=".$v; + } + $i++; + if ($i < $back_count) + $explain .= "[!br!]-------------------"; + if (!isset($tmp1)) + $tmp1 = $tmp; // Pick off the immediate caller as the source + } + if (isset($tmp1)) $source_call = $tmp1; + else $source_call = 'Root level'; + } + else + { + $source_call = $e107->fix_windows_paths($source_call); // Needed for Windoze hosts. + $source_call = str_replace($e107->file_path, "", $source_call); // We really just want a e107 root-relative path. Strip out the root bit + $source_call = $tp->toDB($source_call, true, false, 'no_html'); + } + // else $source_call is a string + + // Save new rolling log record + $this->rldb->insert("dblog", "0, ".intval($time_sec).', '.intval($time_usec).", '{$importance}', '{$eventcode}', {$userid}, '{$userstring}', '{$userIP}', '{$source_call}', '{$event_title}', '{$explain}' "); + + // Now delete any old stuff + if(!empty($pref['roll_log_days'])) + { + $days = intval($pref['roll_log_days']); + $this->rldb->delete("dblog", "dblog_datestamp < '".intval(time() - ($days * 86400))."' "); + } + } + + if ($finished) + exit; // Optional abort for all logs + } + + public function setCurrentPlugin($plugdir) + { + $this->_current_plugin = $plugdir; + + return $this; + } + + /**-------------------------------------- + * USER AUDIT ENTRY + *-------------------------------------- + * Log user-related events + * @param int $event_code is a defined constant (see above) which specifies the event + * @param array $event_data is an array of data fields whose keys and values are logged (usually user data, but doesn't have to be - can add messages here) + * @param int $id + * @param string $u_name + * both $id and $u_name are left blank except for admin edits and user login, where they specify the id and login name of the 'target' user + * + * @return bool + */ + function user_audit($event_type, $event_data, $id = '', $u_name = '') + { + list($time_usec, $time_sec) = explode(" ", microtime()); // Log event time immediately to minimise uncertainty + + $time_usec = $time_usec * 1000000; + + if(!is_numeric($event_type)) + { + $title = "User Audit Event-Type Failure: "; + $title .= (string) $event_type; + $debug = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,4); + $debug[0] = e_REQUEST_URI; + + $this->e_log_event(4, $debug[1]['file']."|".$debug[1]['function']."@".$debug[1]['line'], "USERAUDIT", $title, $debug, FALSE); + return false; + } + + // See whether we should log this + $user_logging_opts = e107::getConfig()->get('user_audit_opts'); + + if (!isset($user_logging_opts[$event_type])) // Finished if not set to log this event type + { + return false; + } + + if(empty($event_data)) + { + $backt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,4); + $event_data = $backt; + } + + + if($this->rldb == null) + { + $this->rldb = e107::getDb('rldb'); // Better use our own db - don't know what else is going on + } + + if(!empty($id)) + { + $userid = $id; + } + else + { + $userid = (USER === true) ? USERID : 0; + } + + if(!empty($u_name)) + { + $userstring = $u_name; + } + else + { + $userstring = (USER === true ? USERNAME : "LAN_ANONYMOUS"); + } + + $userIP = e107::getIPHandler()->getIP(false); + + $eventcode = 'USER_'.$event_type; + + $title = 'LAN_AUDIT_LOG_0'.$event_type; // This creates a string which will be displayed as a constant + + $insertQry = array( + 'dblog_id' => 0, + 'dblog_datestamp' => intval($time_sec), + 'dblog_microtime' => intval($time_usec), + 'dblog_eventcode' => $eventcode, + 'dblog_user_id' => $userid, + 'dblog_user_name' => $userstring, + 'dblog_ip' => $userIP, + 'dblog_title' => $title, + 'dblog_remarks' => print_r($event_data,true), + ); + + if($this->rldb->insert("audit_log", $insertQry)) + { + return true; + } + + return false; + } + + + /* Legacy function probably not needed + function get_log_events($count = 15, $offset) + { + global $sql; + $count = intval($count); + return "Not implemented yet"; + } + */ + + + + /** + * Removes all events older than $days, or truncates the table if $days == false + * + * @param integer|false $days + * @return void + */ + public function purge_log_events($days) + { + global $sql; + if ($days == false) + { // $days is false, so truncate the log table + $sql->gen("TRUNCATE TABLE #dblog "); + } + else + { // $days is set, so remove all entries older than that. + $days = intval($days); + $mintime = $days * 24 * 60 * 60; + $time = time() - $mintime; + $sql->db_Delete("dblog", "WHERE `dblog_datestamp` < {$time}", true); + } + } + + //-------------------------------------- + // HELPER ROUTINES + //-------------------------------------- + /** + * Generic routine to log changes to an array. Only elements in $new are checked + * + * @param array $new - most recent data being saved + * @param array $old existing data - array is updated with changes, but not saved anywhere + * @param string $event - LAN define or string used as title in log + * + * @return bool true if changes found and logged, false otherwise. + */ + function logArrayDiffs($new, $old, $event, $logNow = true) + { + // $changes = array(); + + $changes = array_diff_recursive($new,$old); + + if (count($changes)) + { + if($logNow) + { + $this->add($event, print_r($changes,true), E_LOG_INFORMATIVE, ''); + } + else + { + $this->logMessage($changes, LOG_MESSAGE_NODISPLAY, E_MESSAGE_INFO); + } + + return TRUE; + } + + return FALSE; + } + + + /** + * Logs an entry with all the data from an array, one field per line. + * @deprecated + * @param string $event - LAN define or string used as title in log + * @param array $target - data to be logged + * @param string $extra - if non-empty, it goes on the first line. + * @param array $niceNames - Normally data is logged in the format keyname=>value, one per line. + * If the $niceName array exists and has a definition, the 'nice Name' is displayed instead of the key name + * + * @return none + */ + public function logArrayAll($event, $target, $extra = '', $niceNames = NULL) + { + + if($extra == '' && $niceNames == null) + { + return $this->add($event, $target, E_LOG_INFORMATIVE, ''); // supports arrays + + } + + + $logString = ''; + if ($extra) + { + $logString = $extra.'[!br!]'; + } + $spacer = ''; + $checkNice = ($niceNames != NULL) && is_array($niceNames); + foreach ($target as $k=>$v) + { + if ($checkNice && isset($niceNames[$k]['niceName'])) + { + $logString .= $spacer.$niceNames[$k]['niceName'].'=>'.$v; + } + else + { + $logString .= $spacer.$k.'=>'.$v; + } + $spacer = '[!br!]'; + } + $this->add($event, $logString, E_LOG_INFORMATIVE, ''); + } + + /** + * The next two routines accept and buffers messages which are destined for both admin log and message handler + */ + + /** + * Add a message to the queue + * + * @param string|array $text - the message text for logging/display + * @param int $type - the 'importance' of the message. E_MESSAGE_SUCCESS|E_MESSAGE_ERROR|E_MESSAGE_INFO|E_MESSAGE_DEBUG|E_MESSAGE_NODISPLAY + * (Values as used in message handler, apart from the last, which causes the message to not be passed to the message handler + * @param boolean|int $logLevel - TRUE to give same importance as for message display. FALSE to not log. + * one of the values specified for $mesLevel to determine the prefix attached to the log message + * @param boolean $session add session message + * + * @return e_admin_log + */ + public function logMessage($text, $type = '', $logLevel = TRUE, $session = FALSE) + { + + if(is_array($text)) + { + $text = print_r($text,true); + } + elseif(empty($text)) + { + $bt = debug_backtrace(true); + e107::getMessage()->addDebug("Log Message was empty: ".print_a($bt[1],true)); + return $this; // changing to text will break chained methods. + } + + if(!$type) $type = E_MESSAGE_INFO; + if($logLevel === TRUE) $logLevel = $type; + + $logArray = array('message' => $text, 'dislevel' => $type, 'loglevel' => $logLevel, 'session' => $session, 'time'=>time()); + + $this->_messages[] = $logArray; + $this->_allMessages[] = $logArray; + + return $this; + } + + + + /** + * @DEPRECATED + * BC Alias for addSuccess(); + */ + public function logSuccess($text, $message = true, $session = false) + { + return $this->addSuccess($text,$message,$session); + } + + + + /** + * @DEPRECATED + * BC Alias for addError(); + */ + public function logError($text, $message = true, $session = false) + { + return $this->addError($text,$message,$session); + } + + + /** + * Add a success message to the log queue + * + * @param string|array $text + * @param boolean $message if true - register with eMessage handler + * @param boolean $session add session message + * @return e_admin_log + */ + public function addSuccess($text, $message = true, $session = false) + { + return $this->logMessage($text, ($message ? E_MESSAGE_SUCCESS : LOG_MESSAGE_NODISPLAY), E_MESSAGE_SUCCESS, $session); + } + + + /** + * Add an error message to the log queue + * + * @param string $text + * @param boolean $message if true (default) - register with eMessage handler, set to false to hide. + * @param boolean $session add session message + * @return e_admin_log + */ + public function addError($text, $message = true, $session = false) + { + return $this->logMessage($text, ($message ? E_MESSAGE_ERROR : LOG_MESSAGE_NODISPLAY), E_MESSAGE_ERROR, $session); + } + + + /** + * Add an Debug message to the log queue + * + * @param string $text + * @param boolean $message if true (default) - register with eMessage handler, set to false to hide . + * @param boolean $session add session message + * @return e_admin_log + */ + public function addDebug($text, $message = true, $session = false) + { + return $this->logMessage($text, ($message ? E_MESSAGE_DEBUG : LOG_MESSAGE_NODISPLAY), E_MESSAGE_DEBUG, $session); + } + + + /** + * Add an Warning message to the log queue + * + * @param string $text + * @param boolean $message if true (default) - register with eMessage handler, set to false to hide. + * @param boolean $session add session message + * @return e_admin_log + */ + public function addWarning($text, $message = true, $session = false) + { + return $this->logMessage($text, ($message ? E_MESSAGE_WARNING : LOG_MESSAGE_NODISPLAY), E_MESSAGE_WARNING, $session); + } + + + /** + * Add an array to the log queue + * @param $array + * @param $oldArray (optional) - when included, only the changes between the arrays is saved. + * @param $type (optional) default: LOG_MESSAGE_NODISPLAY. or E_MESSAGE_WARNING, E_MESSAGE_DEBUG, E_MESSAGE_SUCCESS + */ + public function addArray($array, $oldArray= null, $type = LOG_MESSAGE_NODISPLAY , $session = false) + { + if(is_array($oldArray)) + { + $text = array_diff_recursive($array,$oldArray); // Located in core_functions.php + if(count($text) < 1) + { + $text = "No differences found"; + } + + } + else + { + $text = $array; + } + + return $this->logMessage($text, $type, $type, $session); + } + + /** + * Empty the messages - pass to both admin log and message handler + * + * @param string $logTitle - title for log entry + * @param int $logImportance - passed directly to admin log + * @param string $logEventCode - passed directly to admin log + * @param string $mstack [optional] message stack passed to message handler + * @return e_admin_log + */ + public function flushMessages($logTitle, $logImportance = E_LOG_INFORMATIVE, $logEventCode = '', $mstack = false, $target =LOG_TO_ADMIN) + { + $mes = e107::getMessage(); + + $resultTypes = array(E_MESSAGE_SUCCESS => 'Success', E_MESSAGE_ERROR => 'Fail'); // Add LANS here. Could add other codes + $separator = ''; + $logString = ''; + foreach ($this->_messages as $m) + { + if ($m['loglevel'] !== FALSE) + { + $logString .= $separator; + if ($m['loglevel'] == LOG_MESSAGE_NODISPLAY) { $logString .= ' '; } // Indent supplementary messages + // Not sure about next line - might want to log the
as text, rather than it forcing a newline + $logString .= strip_tags(str_replace(array('
', '
', '
'), '[!br!]', $m['message'])); + if (isset($resultTypes[$m['loglevel']])) + { + $logString .= ' - '.$resultTypes[$m['loglevel']]; + } + $separator = '[!br!]'; + } + if ($m['dislevel'] != LOG_MESSAGE_NODISPLAY) + { + if($mstack) + { + $mes->addStack($m['message'], $mstack, $m['dislevel'], $m['session']); + // move to main stack OUTSIDE if needed + } + else $mes->add($m['message'], $m['dislevel'], $m['session']); + } + } + $this->add($logTitle, $logString, $logImportance, $logEventCode, $target); + $this->_messages = array(); // Clear the memory for reuse + + return $this; + } + + + + + + /** + * Clear all messages in 'memory'. + */ + public function clear() + { + $this->_messages = array(); + + return $this; + } + + + /** + * Save Message stack to File. + */ + private function saveToFile($logTitle='', $append=false, $opts = array()) + { + if($this->logFile == null) + { + return; + } + + if(count($this->_allMessages)) + { + $head = " e107 CMS Log file : ".$logTitle." ".date('Y-m-d_H-i-s')."\n"; + $head .= "-------------------------------------------------------------------------------------------\n\n"; + } + else + { + return; + } + + $text = ''; + + foreach($this->_allMessages as $m) + { + $text .= date('Y-m-d H:i:s', $m['time'])." \t".str_pad($m['loglevel'],10," ",STR_PAD_RIGHT)."\t".strip_tags($m['message'])."\n"; + } + + $date = ($append == true) ? date('Y-m-d') : date('Y-m-d_H-i-s').'_'.crc32($text); + + + + $dir = e_LOG; + + if(empty($this->_current_plugin)) + { + $this->_current_plugin = deftrue('e_CURRENT_PLUGIN'); + } + + if(!empty($this->_current_plugin)) // If it's a plugin, create a subfolder. + { + $dir = e_LOG.$this->_current_plugin."/"; + + if(!is_dir($dir)) + { + mkdir($dir,0755); + } + } + + $fileName = $dir.$date."_".$this->logFile.".log"; + + if(!empty($opts['filename'])) + { + $fileName = $dir.basename($opts['filename']); + } + + if($append == true) + { + $app = FILE_APPEND; + if(!file_exists($fileName)) + { + $text = $head . $text; + } + } + else + { + $app = null; + $text = $head . $text; + } + + if(file_put_contents($fileName, $text, $app)) + { + $this->_allMessages = array(); + $this->_current_plugin = null; + return $this->logFile; + } + elseif(getperms('0') && E107_DEBUG_LEVEL > 0) + { + e107::getMessage()->addDebug("Couldn't Save to Log File: ".$fileName); + } + + $this->_current_plugin = null; + + return false; + } + + + + + /** + * Set and save accumulated log to a file. + * Use addDebug(), addError() or addSuccess() prior to executing. + * @param string name without the extension. (ie. date prefix and .log suffix will be added automatically) + * @param string Title for use inside the Log file + * @param boolean true = append to file, false = new file each save. + */ + public function toFile($name, $logTitle='',$append=false, $opts=array()) + { + + $this->logFile = $name; + $file = $this->saveToFile($logTitle,$append,$opts); + + $this->logFile = null; + return $file; + } + + +} diff --git a/e107_handlers/application.php b/e107_handlers/application.php index baa627f79..3313ebda2 100644 --- a/e107_handlers/application.php +++ b/e107_handlers/application.php @@ -1,4962 +1,4962 @@ -_request = (e_HTTP === '/') ? ltrim(e_REQUEST_URI,'/') : str_replace(e_HTTP,'', e_REQUEST_URI) ; - - $this->_config = e107::getUrlConfig(); - $this->_alias = e107::getPref('e_url_alias'); - - $this->_rootnamespace = e107::getPref('url_main_module'); - $this->_legacy = e107::getPref('url_config'); - $this->_legacyAliases = e107::getPref('url_aliases'); - - - $this->setRootNamespace(); - - } - - /** - * Detect older e_url system. - * @return bool - */ - private function isLegacy() - { - - $arr = (!empty($this->_legacyAliases[e_LAN])) ? array_merge($this->_legacy,$this->_legacyAliases[e_LAN]) : $this->_legacy; - - $list = array_keys($arr); - - foreach($list as $leg) - { - if(strpos($this->_request,$leg.'/') === 0 || $this->_request === $leg) - { - return true; - } - - } - - return false; - } - - - /** - * @return string - */ - public function getInclude() - { - return $this->_include; - } - - - - private function setRootNamespace() - { - - $plugs = array_keys($this->_config); - - if(!empty($this->_rootnamespace) && in_array($this->_rootnamespace,$plugs)) // Move rootnamespace check to the end of the list. - { - $v = $this->_config[$this->_rootnamespace]; - unset($this->_config[$this->_rootnamespace]); - $this->_config[$this->_rootnamespace] = $v; - } - - } - - - public function run() - { - $pref = e107::getPref(); - $tp = e107::getParser(); - - if(empty($this->_config) || empty($this->_request) || $this->_request === 'index.php' || $this->isLegacy() === true) - { - return false; - } - - $replaceAlias = array('{alias}\/?','{alias}/?','{alias}\/','{alias}/',); - - foreach($this->_config as $plug=>$cfg) - { - if(empty($pref['e_url_list'][$plug])) // disabled. - { - e107::getDebug()->log('e_URL for '.$plug.' is disabled.'); - continue; - } - - foreach($cfg as $k=>$v) - { - - if(empty($v['regex'])) - { - // e107::getMessage()->addDebug("Skipping empty regex: ".$k.""); - continue; - } - - - if(!empty($v['alias'])) - { - $alias = (!empty($this->_alias[e_LAN][$plug][$k])) ? $this->_alias[e_LAN][$plug][$k] : $v['alias']; - // e107::getMessage()->addDebug("e_url alias found: ".$alias.""); - if(!empty($this->_rootnamespace) && $this->_rootnamespace === $plug) - { - $v['regex'] = str_replace($replaceAlias, '', $v['regex']); - } - else - { - - $v['regex'] = str_replace('{alias}', $alias, $v['regex']); - } - } - - - $regex = '#'.$v['regex'].'#'; - - if(empty($v['redirect'])) - { - continue; - } - - - $newLocation = preg_replace($regex, $v['redirect'], $this->_request); - - if($newLocation != $this->_request) - { - $redirect = e107::getParser()->replaceConstants($newLocation); - list($file,$query) = explode("?", $redirect,2); - - $get = array(); - if(!empty($query)) - { - // issue #3171 fix double ampersand in case of wrong query definition - $query = str_replace('&&', '&', $query); - parse_str($query,$get); - } - - - foreach($get as $gk=>$gv) - { - $_GET[$gk] = $gv; - } - - e107::getDebug()->log('e_URL in '.$plug.' with key: '.$k.' matched '.$v['regex'].' and included: '.$file.' with $_GET: '.print_a($_GET,true),1); - - if(file_exists($file)) - { - define('e_CURRENT_PLUGIN', $plug); - define('e_QUERY', str_replace('&&', '&', $query)); // do not add to e107_class.php - define('e_URL_LEGACY', $redirect); - - $this->_include= $file; - return true; - // exit; - } - elseif(getperms('0')) - { - - echo "
"; - echo "

SEF Debug Info

"; - echo "File missing: ".$file; - echo "
Matched key: ".$k.""; - print_a($v); - echo "
"; - - } - - } - } - - } - - - - - } - - - /** - * Singleton implementation - * @return e_url - */ - public static function instance() - { - if(null == self::$_instance) - { - self::$_instance = new self(); - } - return self::$_instance; - } - - - -} - - - - - -/** - * e107 Front controller - */ -class eFront -{ - /** - * Singleton instance - * @var eFront - */ - private static $_instance; - - /** - * @var eDispatcher - */ - protected $_dispatcher; - - /** - * @var eRequest - */ - protected $_request; - - /** - * @var eRouter - */ - protected $_router; - - - protected $_response; - - /** - * @var string path to file to include - the old deprecated way of delivering content - */ - protected static $_legacy = ''; - - /** - * Constructor - */ - private function __construct() - { - } - - /** - * Cloning not allowed - * - */ - private function __clone() - { - } - - /** - * Singleton implementation - * @return eFront - */ - public static function instance() - { - if(null == self::$_instance) - { - self::$_instance = new self(); - } - return self::$_instance; - } - - /** - * Dispatch - */ - public function dispatch(eRequest $request = null, eResponse $response = null, eDispatcher $dispatcher = null) - { - if(null === $request) - { - if(null === $this->getRequest()) - { - $request = new eRequest(); - $this->setRequest($request); - } - else $request = $this->getRequest(); - } - elseif(null === $this->getRequest()) $this->setRequest($request); - - if(null === $response) - { - if(null === $this->getResponse()) - { - $response = new eResponse(); - $this->setResponse($response); - } - else $response = $this->getResponse(); - } - elseif(null === $this->getRequest()) $this->setRequest($request); - - - if(null === $dispatcher) - { - if(null === $this->getDispatcher()) - { - $dispatcher = new eDispatcher(); - $this->setDispatcher($dispatcher); - } - else $dispatcher = $this->getDispatcher(); - } - elseif(null === $this->getDispatcher()) $this->setDispatcher($dispatcher); - - - // set dispatched status true, required for checkLegacy() - $request->setDispatched(true); - - $router = $this->getRouter(); - - // If current request not already routed outside the dispatch method, route it - if(!$request->routed) $router->route($request); - - $c = 0; - // dispatch loop - do - { - $c++; - if($c > 100) - { - throw new eException("Too much dispatch loops", 1); - } - - // dispatched status true on first loop - $router->checkLegacy($request); - - // dispatched by default - don't allow legacy to alter dispatch status - $request->setDispatched(true); - - // legacy mod - return control to the bootstrap - if(self::isLegacy()) - { - return; - } - - // for the good players - dispatch loop - no more BC! - try - { - $dispatcher->dispatch($request, $response); - } - catch(eException $e) - { - echo $request->getRoute().' - '.$e->getMessage(); - exit; - } - - - } while (!$request->isDispatched()); - } - - /** - * Init all objects required for request dispatching - * @return eFront - */ - public function init() - { - $request = new eRequest(); - $this->setRequest($request); - - $dispatcher = new eDispatcher(); - $this->setDispatcher($dispatcher); - - $router = new eRouter(); - $this->setRouter($router); - - /** @var eResponse $response */ - $response = e107::getSingleton('eResponse'); - $this->setResponse($response); - - return $this; - } - - /** - * Dispatch - * @param string|eRequest $route - */ - public function run($route = null) - { - if($route) - { - if(is_object($route) && ($route instanceof eRequest)) $this->setRequest($route); - elseif(null !== $route && null !== $this->getRequest()) $this->getRequest()->setRoute($route); - } - try - { - $this->dispatch(); - } - catch(eException $e) - { - echo $e->getMessage(); - exit; - } - - } - - /** - * Application instance (e107 class) - * @return e107 - */ - public static function app() - { - return e107::getInstance(); - } - - /** - * Get dispatcher instance - * @return eDispatcher - */ - public function getDispatcher() - { - return $this->_dispatcher; - } - - /** - * Set dispatcher - * @param eDispatcher $dispatcher - * @return eFront - */ - public function setDispatcher(eDispatcher $dispatcher) - { - $this->_dispatcher = $dispatcher; - return $this; - } - - /** - * Get request instance - * @return eRequest - */ - public function getRequest() - { - return $this->_request; - } - - /** - * Set request - * @param eRequest $request - * @return eFront - */ - public function setRequest(eRequest $request) - { - $this->_request = $request; - return $this; - } - - /** - * Get response instance - * @return eResponse - */ - public function getResponse() - { - return $this->_response; - } - - /** - * Set response - * @param eResponse $response - * @return eFront - */ - public function setResponse(eResponse $response) - { - $this->_response = $response; - return $this; - } - - /** - * Get router instance - * @return eRouter - */ - public function getRouter() - { - return $this->_router; - } - - /** - * Set router instance - * @return eFront - */ - public function setRouter(eRouter $router) - { - $this->_router = $router; - return $this; - } - - /** - * Set/get legacy status of the current request - * @param boolean $status - * @return boolean - */ - public static function isLegacy($status = null) - { - if(null !== $status) - { - if(!empty($status[0]) && ($status[0] === '{')) - { - $status = e107::getParser()->replaceConstants($status); - } - self::$_legacy = $status; - } - return self::$_legacy; - } -} - -/** - * e107 Dispatcher - * It decides how to dispatch the request. - */ -class eDispatcher -{ - protected static $_configObjects = array(); - - public function dispatch(eRequest $request = null, eResponse $response = null) - { - $controllerName = $request->getControllerName(); - $moduleName = $request->getModuleName(); - $className = $this->isDispatchable($request, false); - - // dispatch based on rule settings - if(!$className) - { - if($controllerName == 'index') // v2.x upgrade has not been run yet. - { - e107::getRedirect()->redirect(e_ADMIN."admin.php"); - } - - throw new eException("Invalid controller '".$controllerName."'"); - } - - $controller = new $className($request, $response); - if(!($controller instanceof eController)) - { - throw new eException("Controller $controller is not an instance of eController"); - } - - $actionName = $request->getActionMethodName(); - - ob_start(); - - $controller->dispatch($actionName); - - $content = ob_get_contents(); - ob_end_clean(); - - $response->appendBody($content); - unset($controller); - } - - /** - * Get path to the e_url handler - * @param string $module - * @param string $location plugin|core|override - * @param boolean $sc - * @return string path - */ - public static function getConfigPath($module, $location, $sc = false) - { - $tmp = explode('/', $location); - $custom = ''; - $location = $tmp[0]; - if(isset($tmp[1]) && !empty($tmp[1])) - { - $custom = $tmp[1].'_'; - } - unset($tmp); - if($module !== '*') $module .= '/'; - - switch ($location) - { - case 'plugin': - //if($custom) $custom = 'url/'.$custom; - if(!defined('e_CURRENT_PLUGIN')) - { - define('e_CURRENT_PLUGIN', rtrim($module,'/')); // TODO Move to a better location. - } - return $sc ? '{e_PLUGIN}'.$module.'url/'.$custom.'url.php' : e_PLUGIN.$module.'url/'.$custom.'url.php'; - break; - - case 'core': - if($module === '*') return $sc ? '{e_CORE}url/' : e_CORE.'url/'; - return $sc ? '{e_CORE}url/'.$module.$custom.'url.php' : e_CORE.'url/'.$module.$custom.'url.php'; - break; - - case 'override': - if($module === '*') return $sc ? '{e_CORE}override/url/' : e_CORE.'override/url/' ; - return $sc ? '{e_CORE}override/url/'.$module.$custom.'url.php' : e_CORE.'override/url/'.$module.$custom.'url.php' ; - break; - - default: - return null; - break; - } - } - - /** - * Get path to url configuration subfolders - * @param string $module - * @param string $location plugin|core|override - * @param boolean $sc - * @return string path - */ - public static function getConfigLocationPath($module, $location, $sc = false) - { - switch ($location) - { - case 'plugin': - return $sc ? '{e_PLUGIN}'.$module.'/url/' : e_PLUGIN.$module.'/url/'; - break; - - case 'core': - return $sc ? '{e_CORE}url/'.$module.'/' : e_CORE.'url/'.$module.'/'; - break; - - case 'override': - return $sc ? '{e_CORE}override/url/'.$module.'/' : e_CORE.'override/url/'.$module.'/'; - break; - - default: - return null; - break; - } - } - - /** - * Get dispatch system path - * @param string $location plugin|core|override - * @param string $plugin required only when $location is plugin - * @param boolean $sc - * @return string path - */ - public static function getDispatchLocationPath($location, $plugin = null, $sc = false) - { - switch ($location) - { - case 'plugin': - if(!$plugin) return null; - return $sc ? '{e_PLUGIN}'.$plugin.'/controllers/' : e_PLUGIN.$plugin.'/controllers/'; - break; - - case 'core': - return $sc ? '{e_CORE}controllers/' : e_CORE.'controllers/'; - break; - - case 'override': - return $sc ? '{e_CORE}override/controllers/' : e_CORE.'override/controllers/'; - break; - - default: - return null; - break; - } - } - - /** - * Get full dispatch system path - * @param string $module - * @param string $location plugin|core|override - * @param boolean $sc - * @return string path - */ - public static function getDispatchPath($module, $location, $sc = false) - { - switch ($location) - { - case 'plugin': - return $sc ? '{e_PLUGIN}'.$module.'/controllers/' : e_PLUGIN.$module.'/controllers/'; - break; - - case 'core': - return $sc ? '{e_CORE}controllers/'.$module.'/' : e_CORE.'controllers/'.$module.'/'; - break; - - case 'override': - return $sc ? '{e_CORE}override/controllers/'.$module.'/' : e_CORE.'override/controllers/'.$module.'/'; - break; - - default: - return null; - break; - } - } - - /** - * Get include path to a given module/controller - * - * @param string $module valid module name - * @param string $controller controller name - * @param string $location core|plugin|override - * @param boolean $sc return relative (false) OR shortcode (true) path - * @return string controller path - */ - public static function getControllerPath($module, $controller, $location = null, $sc = false) - { - if(null === $location) $location = self::getDispatchLocation($module); - - return ($location ? self::getDispatchPath($module, $location, $sc).$controller.'.php': null); - } - - /** - * Get class name of a given module/controller - * - * @param string $module valid module name - * @param string $controllerName controller name - * @param string $location core|plugin|override - * @return string controller path - */ - public static function getControllerClass($module, $controllerName, $location = null) - { - if(null === $location) $location = self::getDispatchLocation($module); - - return ($location ? $location.'_'.$module.'_'.$controllerName.'_controller' : null); - } - - - /** - * Get controller object - * - * @param eRequest $request - * @param boolean $checkOverride whether to check the override location - * @return eController null if not dispatchable - */ - public function getController(eRequest $request, $checkOverride = true) - { - $class_name = $this->isDispatchable($request, true, $checkOverride); - if(!$class_name) return null; - - return new $class_name(); - } - - /** - * Check if given module/controller is dispatchable - * @param string $module valid module name - * @param string $controllerName controller name - * @param string $location core|plugin|override - * @param boolean $checkOverride whether to check the override location - * @return string class name OR false if not dispatchable - */ - public function isDispatchableModule($module, $controllerName, $location, $checkOverride = false) - { - if($checkOverride || $location == 'override') - { - $path = self::getControllerPath($module, $controllerName, 'override', false); - - $class_name = self::getControllerClass($module, $controllerName, 'override'); - if($class_name && !class_exists($class_name, false) && is_readable($path)) include_once($path); - - if($class_name && class_exists($class_name, false)) return $class_name; - } - - // fallback to original dispatch location if any - if($location === 'override') - { - // check for real location - if(($location = eDispatcher::getModuleRealLocation($module)) === null) return false; - } - - if($location !== 'override') - { - $path = self::getControllerPath($module, $controllerName, $location, false); - - $class_name = self::getControllerClass($module, $controllerName, $location); - if(!$class_name) return false; - - if(!class_exists($class_name, false) && is_readable($path)) include_once($path); - - if(class_exists($class_name, false)) return $class_name; - } - return false; - } - - /** - * Automated version of self::isDispatchableModule() - * @param eRequest $request - * @param boolean $checkReflection deep check - proper subclassing, action - * @param boolean $checkOverride try override controller folder first - * @return mixed class name OR false if not dispatchable - */ - public function isDispatchable(eRequest $request, $checkReflection = false, $checkOverride = true) - { - $location = self::getDispatchLocation($request->getModuleName()); - - $controllerName = $request->getControllerName(); - $moduleName = $request->getModuleName(); - $className = false; - - // dispatch based on url_config preference value, if config location is override and there is no - // override controller, additional check against real controller location will be made - if($location) - { - $className = $this->isDispatchableModule($moduleName, $controllerName, $location, $checkOverride); - } - //else - //{ - # Disable plugin check for routes with no config info - prevent calling of non-installed plugins - # We may allow this for plugins which don't have plugin.xml in the future - // $className = $this->isDispatchableModule($moduleName, $controllerName, 'plugin', $checkOverride); - // if(!$className) - //$className = $this->isDispatchableModule($moduleName, $controllerName, 'core', $checkOverride); - //} - - if(empty($className)) return false; - elseif(!$checkReflection) return $className; - - $rfl = new ReflectionClass($className); - $method = $request->getActionMethodName(); - if($rfl->isSubclassOf('eController') && $rfl->hasMethod($method) && $rfl->getMethod($method)->isPublic() && !$rfl->getMethod($method)->isStatic()) - return $className; - - return false; - } - - /** - * Get class name of a given module config - * - * @param string $module valid module name - * @param string $location core|plugin|override[/custom] - * @return string controller path - */ - public static function getConfigClassName($module, $location) - { - $tmp = explode('/', $location); - $custom = ''; - $location = $tmp[0]; - if(isset($tmp[1]) && !empty($tmp[1])) - { - $custom = $tmp[1].'_'; - } - unset($tmp); - $module .= '_'; - - // we need to prepend location to avoid namespace colisions - return $location.'_'.$module.$custom.'url'; - } - - /** - * Get config object for a module - * - * @param string $module valid module name - * @param string $location core|plugin|override[/custom] - * @return eUrlConfig - */ - public static function getConfigObject($module, $location = null) - { - if(null === $location) - { - $location = self::getModuleConfigLocation($module); - if(!$location) return null; - } - $reg = $module.'/'.$location; - if(isset(self::$_configObjects[$reg])) return self::$_configObjects[$reg]; - $className = self::getConfigClassName($module, $location); - if(!class_exists($className, false)) - { - $path = self::getConfigPath($module, $location, false); - if(!is_readable($path)) return null; - include_once($path); - - if(!class_exists($className, false)) return null; - } - $obj = new $className(); - $obj->init(); - self::$_configObjects[$reg] = $obj; - $obj = null; - - return self::$_configObjects[$reg]; - } - - /** - * Auto discover module location from stored in core prefs data - * @param string $module - * @return mixed - */ - public static function getModuleConfigLocation($module) - { - //retrieve from config prefs - return e107::findPref('url_config/'.$module, ''); - } - - /** - * Auto discover module location from stored in core prefs data - * @param string $module - * @return mixed|null|string - */ - public static function getDispatchLocation($module) - { - //retrieve from prefs - $location = self::getModuleConfigLocation($module); - if(!$location) return null; - - if(($pos = strpos($location, '/'))) //can't be 0 - { - return substr($location, 0, $pos); - } - return $location; - } - - - /** - * Auto discover module real location (and not currently set from url adminsitration) from stored in core prefs data - * @param string $module - */ - public static function getModuleRealLocation($module) - { - //retrieve from prefs - $searchArray = e107::findPref('url_modules'); - if(!$searchArray) return null; - - $search = array('core', 'plugin', 'override'); - - foreach ($search as $location) - { - $_searchArray = vartrue($searchArray[$location], array()); - if(in_array($module, $_searchArray)) return $location; - } - return null; - } -} - -/** - * URL manager - parse and create URLs based on rules set - * Inspired by Yii Framework UrlManager - */ -class eRouter -{ - /** - * Configuration array containing all available syste routes and route object configuration values - * @var array - */ - protected $_rules = array(); - - /** - * List of all system wide available aliases - * This includes multi-lingual configurations as well - * @var array - */ - protected $_aliases = array(); - - /** - * Cache for rule objects - * @var array - */ - protected $_parsedRules = array(); // array of rule objects - - /** - * Global config values per rule set - * @var array - */ - protected $_globalConfig = array(); - - /** - * Module name which is used for site main namespace - * Example mysite.com/news/News Item => converted to mysite.com/News Item - * NOTE: Could be moved to rules config - * - * @var string - */ - protected $_mainNsModule = ''; - - /** - * Default URL suffix - to be added to end of all urls (e.g. '.html') - * This value can be overridden per rule item - * NOTE could be moved to rules config only - * @var string - */ - public $urlSuffix = ''; - - /** - * @var string GET variable name for route. Defaults to 'route'. - */ - public $routeVar = 'route'; - - /** - * @var string - */ - const FORMAT_GET = 'get'; - - /** - * @var string - */ - const FORMAT_PATH = 'path'; - - /** - * @var string - */ - private $_urlFormat = self::FORMAT_PATH; - - /** - * Not found route - * @var string - */ - public $notFoundRoute = 'system/error/notfound'; - - protected $_defaultAssembleOptions = array('full' => false, 'amp' => '&', 'equal' => '=', 'encode' => true); - - /** - * Not found URL - used when system route not found and 'url_error_redirect' core pref is true - * TODO - user friendly URL ('/system/404') when system config is ready ('/system/404') - * @var string - */ - public $notFoundUrl = 'system/error/404?type=routeError'; - - - - - public function __construct() - { - $this->_init(); - } - - /** - * Init object - * @return void - */ - protected function _init() - { - // Gather all rules, add-on info, cache, module for main namespace etc - $this->_loadConfig() - ->setAliases(); - // we need config first as setter does some checks if module can be set as main - $this->setMainModule(e107::getPref('url_main_module', '')); - } - - /** - * Set module for default namespace - * @param string $module - * @return eRouter - */ - public function setMainModule($module) - { - if(!$module || !$this->isModule($module) || !$this->getConfigValue($module, 'allowMain')) return $this; - $this->_mainNsModule = $module; - return $this; - } - - /** - * Get main url namespace module - * @return string - */ - public function getMainModule() - { - return $this->_mainNsModule; - } - - /** - * Check if given module is the main module - * @param string $module - * @return boolean - */ - public function isMainModule($module) - { - return ($this->_mainNsModule === $module); - } - - - /** - * @return string get|path - */ - public function getUrlFormat() - { - return $this->_urlFormat; - } - - - /** - * Load config and url rules, if not available - build it on the fly - * @return eRouter - */ - protected function _loadConfig() - { - if(!is_readable(e_CACHE_URL.'config.php')) $config = $this->buildGlobalConfig(); - else $config = include(e_CACHE_URL.'config.php'); - - if(!$config) $config = array(); - - $rules = array(); - - foreach ($config as $module => $c) - { - $rules[$module] = $c['rules']; - unset($config[$module]['rules']); - $config[$module] = $config[$module]['config']; - } - $this->_globalConfig = $config; - $this->setRuleSets($rules); - - return $this; - } - - public static function clearCache() - { - if(file_exists(e_CACHE_URL.'config.php')) - { - @unlink(e_CACHE_URL.'config.php'); - } - } - - /** - * Build unified config.php - */ - public function buildGlobalConfig($save = true) - { - $active = e107::getPref('url_config', array()); - - $config = array(); - foreach ($active as $module => $location) - { - $_config = array(); - $obj = eDispatcher::getConfigObject($module, $location); - $path = eDispatcher::getConfigPath($module, $location, true); - - if(null !== $obj) - { - $_config = $obj->config(); - $_config['config']['configPath'] = $path; - $_config['config']['configClass'] = eDispatcher::getConfigClassName($module, $location); - } - if(!isset($_config['config'])) $_config['config'] = array(); - - $_config['config']['location'] = $location; - if(!isset($_config['config']['format']) || !in_array($_config['config']['format'], array(self::FORMAT_GET, self::FORMAT_PATH))) - { - $_config['config']['format'] = $this->getUrlFormat(); - } - - if(!isset($_config['rules'])) $_config['rules'] = array(); - - foreach ($_config['rules'] as $pattern => $rule) - { - if(!is_array($rule)) - { - $_config['rules'][$pattern] = array($rule); - } - } - - $config[$module] = $_config; - } - - if($save) - { - $fileContent = 'mode = 'fname'; - $files = $file->setFileInfo('fname') - ->get_files($path, '^([a-z_]{1,}_)?url\.php$'); - - - foreach ($files as $file) - { - if(null === $location) - { - $c = eRouter::file2config($file, $location); - if($c) $ret[] = $c; - continue; - } - $ret[] = eRouter::file2config($file, $location); - } - return $ret; - } - - /** - * Convert filename to configuration string - * @param string $filename - * @param string $location core|plugin|override - */ - public static function file2config($filename, $location = '') - { - if($filename == 'url.php') return $location; - if($location) $location .= '/'; - return $location.substr($filename, 0, strrpos($filename, '_')); - } - - /** - * Detect all available system url modules, used as a map on administration configuration path - * and required (same structure) {@link from eDispatcher::adminBuildConfig()) - * This is a very liberal detection, as it doesn't require config file. - * It goes through both config and dispatch locations and registers directory tree as modules - * The only exception are plugins - if plugin requires install (plugin.xml) and it is not installed, - * it won't be registered - * Another important thing is - core has always higher priority, as plugins are not allowed to - * directly override core modules. At this moment, core modules could be overloaded only via override configs (e107_core/override/url/) - * and controllers (e107_core/override/controllers) - * This array is stored as url_modules core preference - * - * @param string $type possible values are all|plugin|core|override - * @return array available system url modules stored as url_modules core preference - */ - public static function adminReadModules($type = 'all') - { - $f = e107::getFile(); - $ret = array('core' => array(), 'plugin' => array(), 'override' => array()); - - if($type == 'all' || $type = 'core') - { - $location = eDispatcher::getDispatchLocationPath('core'); - // search for controllers first - $ret['core'] = $f->get_dirs($location); - - // merge with configs - $configArray = $f->get_dirs(eDispatcher::getConfigPath('*', 'core')); - foreach ($configArray as $config) - { - if(!in_array($config, $ret['core'])) - { - $ret['core'][] = $config; - } - } - sort($ret['core']); - } - - if($type == 'all' || $type = 'plugin') - { - $plugins = $f->get_dirs(e_PLUGIN); - foreach ($plugins as $plugin) - { - // DON'T ALLOW PLUGINS TO OVERRIDE CORE!!! - // This will be possible in the future under some other, more controllable form - if(in_array($plugin, $ret['core'])) continue; - - $location = eDispatcher::getDispatchLocationPath('plugin', $plugin); - $config = eDispatcher::getConfigPath($plugin, 'plugin'); - - if(e107::isInstalled($plugin)) - { - if(is_dir($location) || is_readable($config)) - { - $ret['plugin'][] = $plugin; - } - continue; - } - - // Register only those who don't need install and may be dispatchable - if((!is_readable(e_PLUGIN.$plugin.'/plugin.php') && !is_readable(e_PLUGIN.$plugin.'/plugin.xml'))) - { - if(is_dir($location) || is_readable($config)) - { - $ret['plugin'][] = $plugin; - } - } - } - sort($ret['plugin']); - } - - if($type == 'all' || $type = 'override') - { - // search for controllers first - $location = eDispatcher::getDispatchLocationPath('override'); - $ret['override'] = $f->get_dirs($location); - - // merge with configs - $configArray = $f->get_dirs(eDispatcher::getConfigPath('*', 'override')); - foreach ($configArray as $config) - { - if(!in_array($config, $ret['override'])) - { - $ret['override'][] = $config; - } - } - sort($ret['override']); - - // remove not installed plugin locations, possible only for 'all' type - if($type == 'all') - { - foreach ($ret['override'] as $i => $l) - { - // it's a plugin override, but not listed in current plugin array - remove - if(in_array($l, $plugins) && !in_array($l, $ret['plugin'])) - { - unset($ret['override'][$i]); - } - } - } - } - - return $ret; - } - - /** - * Rebuild configuration array, stored as url_config core preference - * More strict detection compared to {@link eDispatcher::adminReadModules()} - * Current flat array containing config locations per module are rebuilt so that new - * modules are registered, missing modules - removed. Additionally fallback to the default location - * is done if current user defined location is not readable - * @see eDispatcher::adminReadModules() - * @param array current configuration array (url_config core preference like) - * @param array available URL modules as detected by {@link eDispatcher::adminReadModules()} and stored as url_modules core preference value - * @return array new url_config array - */ - public static function adminBuildConfig($current, $adminReadModules = null) - { - if(null === $adminReadModules) $adminReadModules = self::adminReadModules(); - - $ret = array(); - $all = array_unique(array_merge($adminReadModules['core'], $adminReadModules['plugin'], $adminReadModules['override'])); - foreach ($all as $module) - { - if(isset($current[$module])) - { - // current contains custom (readable) config location e.g. news => core/rewrite - if(strpos($current[$module], '/') !== false && is_readable(eDispatcher::getConfigPath($module, $current[$module]))) - { - $ret[$module] = $current[$module]; - continue; - } - - // in all other cases additional re-check will be made - see below - } - - if(in_array($module, $adminReadModules['override'])) - { - // core check - if(in_array($module, $adminReadModules['core'])) - { - $mustHave = is_readable(eDispatcher::getConfigPath($module, 'core')); - $has = is_readable(eDispatcher::getConfigPath($module, 'override')); - - // No matter if it must have, it has e_url config - if($has) $ret[$module] = 'override'; - // It must have but it doesn't have e_url config, fallback - elseif($mustHave && !$has) $ret[$module] = 'core'; - // Rest is always core as controller override is done on run time - else $ret[$module] = 'core'; - } - // plugin check - elseif(in_array($module, $adminReadModules['plugin'])) - { - $mustHave = is_readable(eDispatcher::getConfigPath($module, 'plugin')); - $has = is_readable(eDispatcher::getConfigPath($module, 'override')); - - // No matter if it must have, it has e_url config - if($has) $ret[$module] = 'override'; - // It must have but it doesn't have e_url config, fallback - elseif($mustHave && !$has) $ret[$module] = 'plugin'; - // Rest is always plugin as config is most important, controller override check is done on run time - else $ret[$module] = 'plugin'; - } - // standalone override module - else - { - $ret[$module] = 'override'; - } - - } - // default core location - elseif(in_array($module, $adminReadModules['core'])) - { - $ret[$module] = 'core'; - } - // default plugin location - elseif(in_array($module, $adminReadModules['plugin'])) - { - $ret[$module] = 'plugin'; - } - } - return $ret; - } - - /** - * Detect available config locations (readable check), based on available url_modules {@link eDispatcher::adminReadModules()} core preference arrays - * Used to rebuild url_locations core preference value - * @see eDispatcher::adminBuildConfig() - * @see eDispatcher::adminReadModules() - * @param array $available {@link eDispatcher::adminReadModules()} stored as url_modules core preference - * @return array available config locations, stored as url_locations core preference - */ - public static function adminBuildLocations($available = null) - { - $ret = array(); - if(null === $available) $available = self::adminReadModules(); - - $fl = e107::getFile(); - - // Core - foreach ($available['core'] as $module) - { - // Default module - $ret[$module] = array('core'); - - // read sub-locations - $path = eDispatcher::getConfigLocationPath($module, 'core'); - //$sub = $fl->get_dirs($path); - $sub = eRouter::adminReadConfigs($path); - - if($sub) - { - foreach ($sub as $moduleSub) - { - // auto-override: override available (controller or url config), check for config - if(in_array($module, $available['override']) && is_readable(eDispatcher::getConfigPath($module, 'override/'.$moduleSub))) - { - $ret[$module][] = 'override/'.$moduleSub; - } - // no override available, register the core location - elseif(is_readable(eDispatcher::getConfigPath($module, 'core/'.$moduleSub))) - { - $ret[$module][] = 'core/'.$moduleSub; - } - } - } - } - - - // Plugins - foreach ($available['plugin'] as $module) - { - // Default module - $ret[$module] = array('plugin'); - - // read sub-locations - $path = eDispatcher::getConfigLocationPath($module, 'plugin'); - //$sub = $fl->get_dirs($path); - $sub = eRouter::adminReadConfigs($path); - - if($sub) - { - foreach ($sub as $moduleSub) - { - // auto-override: override available (controller or url config), check for config - if(in_array($module, $available['override']) && is_readable(eDispatcher::getConfigPath($module, 'override/'.$moduleSub))) - { - $ret[$module][] = 'override/'.$moduleSub; - } - // no override available, register the core location - elseif(is_readable(eDispatcher::getConfigPath($module, 'plugin/'.$moduleSub))) - { - $ret[$module][] = 'plugin/'.$moduleSub; - } - } - } - } - - // Go through all overrides, register those who don't belong to core & plugins as standalone core modules - foreach ($available['override'] as $module) - { - // either it is a core/plugin module or e_url.php is not readable - continue - if(in_array($module, $available['core']) || in_array($module, $available['plugin'])) - { - continue; - } - - // Default module - $ret[$module] = array('override'); - - // read sub-locations - $path = eDispatcher::getConfigLocationPath($module, 'override'); - //$sub = $fl->get_dirs($path); - $sub = eRouter::adminReadConfigs($path); - - if($sub) - { - foreach ($sub as $moduleSub) - { - if(is_readable(eDispatcher::getConfigPath($module, 'override/'.$moduleSub))) - { - $ret[$module][] = 'override/'.$moduleSub; - } - } - } - } - - return $ret; - } - - /** - * Match current aliases against currently available module and languages - * @param array $currentAliases url_aliases core preference - * @param array $currentConfig url_config core preference - * @return array cleaned aliases - */ - public static function adminSyncAliases($currentAliases, $currentConfig) - { - if(empty($currentAliases)) return array(); - - $modules = array_keys($currentConfig); - - // remove non existing languages - $lng = e107::getLanguage(); - $lanList = $lng->installed(); - - if(is_array($currentAliases)) - { - foreach ($currentAliases as $lanCode => $aliases) - { - $lanName = $lng->convert($lanCode); - if(!$lanName || !in_array($lanName, $lanList)) - { - unset($currentAliases[$lanCode]); - continue; - } - - // remove non-existing modules - foreach ($aliases as $alias => $module) - { - if(!isset($currentConfig[$module])) unset($currentAliases[$lanCode][$alias]); - } - } - } - return $currentAliases; - } - - /** - * Retrieve global configuration array for a single or all modules - * @param string $module system module - * @return array configuration - */ - public function getConfig($module = null) - { - if(null === $module) return $this->_globalConfig; - - return isset($this->_globalConfig[$module]) ? $this->_globalConfig[$module] : array(); - } - - /** - * Retrieve single value from a module global configuration array - * @param string $module system module - * @return array configuration - */ - public function getConfigValue($module, $key, $default = null) - { - return isset($this->_globalConfig[$module]) && isset($this->_globalConfig[$module][$key]) ? $this->_globalConfig[$module][$key] : $default; - } - - /** - * Get system name of a module by its alias - * Returns null if $alias is not an existing alias - * @param string $alias - * @param string $lan optional language alias check. Example $lan = 'bg' (search for Bulgarian aliases) - * @return string module - */ - public function getModuleFromAlias($alias, $lan = null) - { - if($lan) return e107::findPref('url_aliases/'.$lan.'/'.$alias, null); - return (isset($this->_aliases[$alias]) ? $this->_aliases[$alias] : null); - } - - /** - * Get alias name for a module - * Returns null if module doesn't have an alias - * @param string $module - * @param string $lan optional language alias check. Example $lan = 'bg' (search for Bulgarian aliases) - * @return string alias - */ - public function getAliasFromModule($module, $lan = null) - { - if($lan) - { - $aliases = e107::findPref('url_aliases/'.$lan, array()); - return (in_array($module, $aliases) ? array_search($module, $aliases) : null); - } - return (in_array($module, $this->_aliases) ? array_search($module, $this->_aliases) : null); - } - - /** - * Check if alias exists - * @param string $alias - * @param string $lan optional language alias. Example $lan = 'bg' (search for Bulgarian aliases) - * @return boolean - */ - public function isAlias($alias, $lan = null) - { - if($lan) - { - $aliases = e107::findPref('url_aliases/'.$lan, array()); - return isset($aliases[$alias]); - } - return isset($this->_aliases[$alias]); - } - - /** - * Check if there is an alias for provided module - * @param string $module - * @param string $lan optional language alias check. Example $lan = 'bg' (search for Bulgarian aliases) - * @return boolean - */ - public function hasAlias($module, $lan = null) - { - if($lan) - { - $aliases = e107::findPref('url_aliases/'.$lan, array()); - return in_array($module, $aliases); - } - return in_array($module, $this->_aliases); - } - - /** - * Get all available module aliases - * @param string $lan optional language alias check. Example $lan = 'bg' (search for Bulgarian aliases) - * @return array - */ - public function getAliases($lanCode = null) - { - if($lanCode) - { - return e107::findPref('url_aliases/'.$lanCode, array()); - } - return $this->_aliases; - } - - /** - * Set module aliases - * @param array $aliases - * @return eRouter - */ - public function setAliases($aliases = null) - { - if(null === $aliases) - { - $lanCode = e107::getLanguage()->convert(e_LANGUAGE); - - $aliases = e107::findPref('url_aliases/'.$lanCode, array()); - } - $this->_aliases = $aliases; - - return $this; - } - - /** - * Check if provided module is present in the rules config - * @param string module - * @return boolean - */ - public function isModule($module) - { - return isset($this->_globalConfig[$module]); - } - - /** - * Check if the passed value is valid module or module alias, returns system module - * or null on failure - * @param string $module - * @param boolean $strict check for existence if true - * @return string module - */ - public function retrieveModule($module, $strict = true) - { - if($this->isAlias($module)) - $module = $this->getModuleFromAlias($module); - - if($strict && (!$module || !$this->isModule($module))) - return null; - - return $module; - } - - /** - * Set rule config for this instance - * @param array $rules - * @return void - */ - public function setRuleSets($rules) - { - $this->_rules = $rules; - } - - /** - * Retrieve rule set for a module - * @param string $module - */ - public function getRuleSet($module) - { - return (isset($this->_rules[$module]) ? $this->_rules[$module] : array()); - } - - /** - * Get all rule sets - */ - public function getRuleSets() - { - return $this->_rules; - } - - /** - * Retrive array of eUrlRule objects for given module - */ - public function getRules($module) - { - return $this->_processRules($module); - } - - /** - * Process rule set array, create rule objects - * TODO - rule cache - * @param string $module - * @return array processed rule set - */ - protected function _processRules($module) - { - if(!$this->isModule($module)) return array(); - - if(!isset($this->_parsedRules[$module])) - { - $rules = $this->getRuleSet($module); - $config = $this->getConfig($module); - $this->_parsedRules[$module] = array(); - $map = array('urlSuffix' => 'urlSuffix', 'legacy' => 'legacy', 'legacyQuery' => 'legacyQuery', 'mapVars' => 'mapVars', 'allowVars' => 'allowVars', 'matchValue' => 'matchValue'); - foreach ($rules as $pattern => $set) - { - foreach ($map as $key => $value) - { - if(!isset($set[$value]) && isset($config[$key])) - { - $set[$value] = $config[$key]; - } - } - $this->_parsedRules[$module][$pattern] = $this->createRule($set, $pattern); - } - } - return $this->_parsedRules[$module]; - } - - /** - * Create rule object - * - * @param string $route - * @param string|array $pattern - * @param boolean $cache - * @return eUrlRule - */ - protected function createRule($route, $pattern = null, $cache = false) - { - return new eUrlRule($route, $pattern, $cache); - } - - - private function _debug($label,$val=null, $line=null) - { - if(!deftrue('e_DEBUG_SEF')) - { - return false; - } - - e107::getDebug()->log("

SEF: ".$label . " ".basename(__FILE__)." (".$line.")

".print_a($val,true)); - } - - /** - * Route current request - * @param eRequest $request - * @return boolean - */ - public function route(eRequest $request, $checkOnly = false) - { - $request->routed = false; - - if(isset($_GET[$this->routeVar])) - { - $rawPathInfo = $_GET[$this->routeVar]; - unset($_GET[$this->routeVar]); - $this->_urlFormat = self::FORMAT_GET; - } - else - { - $rawPathInfo = rawurldecode($request->getPathInfo()); - //$this->_urlFormat = self::FORMAT_PATH; - } - - - - // Ignore social trackers when determining route. - $get = eHelper::removeTrackers($_GET); - - // Route to front page - index/index/index route - if(!$rawPathInfo && (!$this->getMainModule() || empty($get))) - { - // front page settings will be detected and front page will be rendered - $request->setRoute('index/index/index'); - $request->addRouteHistory($rawPathInfo); - $request->routed = true; - return true; - } - - // max number of parts is actually 4 - module/controller/action/[additional/pathinfo/vars], here for reference only - $parts = $rawPathInfo ? explode('/', $rawPathInfo, 4) : array(); - - $this->_debug('parts',$parts, __LINE__); - - // find module - check aliases - $module = $this->retrieveModule($parts[0]); - $mainSwitch = false; - - // no module found, switch to Main module (pref) if available - if(null === $module && $this->getMainModule() && $this->isModule($this->getMainModule())) - { - $module = $this->getMainModule(); - $rawPathInfo = $module.'/'.$rawPathInfo; - array_unshift($parts, $module); - $mainSwitch = true; - } - - $request->routePathInfo = $rawPathInfo; - - $this->_debug('module',$module, __LINE__); - $this->_debug('rawPathInfo',$rawPathInfo, __LINE__); - - - // valid module - if(null !== $module) - { - // we have valid module - $config = $this->getConfig($module); - - $this->_debug('config',$module, __LINE__); - - // set legacy state - eFront::isLegacy(varset($config['legacy'])); - - // Don't allow single entry if required by module config - if(vartrue($config['noSingleEntry'])) - { - $request->routed = true; - if(!eFront::isLegacy()) - { - $request->setRoute($this->notFoundRoute); - return false; - } - // legacy entry point - include it later in the bootstrap, legacy query string will be set to current - $request->addRouteHistory($rawPathInfo); - return true; - } - - // URL format - the one set by current config overrides the auto-detection - $format = isset($config['format']) && $config['format'] ? $config['format'] : $this->getUrlFormat(); - - //remove leading module, unnecessary overhead while matching - array_shift($parts); - $rawPathInfo = $parts ? implode('/', $parts) : ''; - $pathInfo = $this->removeUrlSuffix($rawPathInfo, $this->urlSuffix); - - // retrieve rules if any and if needed - $rules = $format == self::FORMAT_PATH ? $this->getRules($module) : array(); - - // Further parsing may still be needed - if(empty($rawPathInfo)) - { - $rawPathInfo = $pathInfo; - } - - // parse callback - if(vartrue($config['selfParse'])) - { - // controller/action[/additional/parms] - if(vartrue($config['urlSuffix'])) $rawPathInfo = $this->removeUrlSuffix($rawPathInfo, $config['urlSuffix']); - $route = $this->configCallback($module, 'parse', array($rawPathInfo, $_GET, $request, $this, $config), $config['location']); - } - // default module route - elseif($format == self::FORMAT_GET || !$rules) - { - $route = $pathInfo; - } - // rules available - try to match an Url Rule - elseif($rules) - { - // $this->_debug('rules',$rules, __LINE__); - - foreach ($rules as $rule) - { - $route = $rule->parseUrl($this, $request, $pathInfo, $rawPathInfo); - - - - if($route !== false) - { - eFront::isLegacy($rule->legacy); // legacy include override - - $this->_debug('rule->legacy',$rule->legacy, __LINE__); - $this->_debug('rule->parseCallback',$rule->parseCallback, __LINE__); - - if($rule->parseCallback) - { - $this->configCallback($module, $rule->parseCallback, array($request), $config['location']); - } - - // parse legacy query string if any - $this->_debug('rule->legacyQuery',$rule->legacyQuery, __LINE__); - - if(null !== $rule->legacyQuery) - { - $obj = eDispatcher::getConfigObject($module, $config['location']); - // eUrlConfig::legacyQueryString set as legacy string by default in eUrlConfig::legacy() method - $vars = new e_vars($request->getRequestParams()); - $vars->module = $module; - $vars->controller = $request->getController(); - $vars->action = $request->getAction(); - if($rule->allowVars) - { - foreach ($rule->allowVars as $key) - { - if(isset($_GET[$key]) && !$request->isRequestParam($key)) - { - // sanitize - $vars->$key = preg_replace('/[^\d\w\-]/', '', $_GET[$key]); - } - } - } - $obj->legacyQueryString = e107::getParser()->simpleParse($rule->legacyQuery, $vars, '0'); - - $this->_debug('obj->legacyQueryString',$obj->legacyQueryString, __LINE__); - unset($vars, $obj); - } - break; - } - } - } - - // append module to be registered in the request object - if(false !== $route) - { - // don't modify if true - request directly modified by config callback - if(!$request->routed) - { - if(eFront::isLegacy()) $this->configCallback($module, 'legacy', array($route, $request), $config['location']); - $route = $module.'/'.$route; - } - } - // No route found, we didn't switched to main module auto-magically - elseif(!$mainSwitch && vartrue($config['errorRoute'])) - { - $route = !$checkOnly ? $module.'/'.$config['errorRoute'] : false; - } - - } - - // final fallback - if(!vartrue($route)) - { - if($request->routed) - { - $route = $request->getRoute(); - } - - if(!$route) - { - $route = $this->notFoundRoute; - eFront::isLegacy(''); // reset legacy - not found route isn't legacy call - $request->routed = true; - if($checkOnly) return false; - ## Global redirect on error option - if(e107::getPref('url_error_redirect', false) && $this->notFoundUrl) - { - $redirect = $this->assemble($this->notFoundUrl, '', 'encode=0&full=1'); - //echo $redirect; exit; - e107::getRedirect()->redirect($redirect, true, 404); - } - } - } - - $this->_debug('route',$route, __LINE__); - - $request->setRoute($route); - $request->addRouteHistory($route); - $request->routed = true; - return true; - } - - /** - * And more BC - * Checks and does some addtional logic if registered module is of type legacy - * @param eRequest $request - * @return void - */ - public function checkLegacy(eRequest $request) - { - $module = $request->getModule(); - - // forward from controller to a legacy module - bad stuff - if(!$request->isDispatched() && $this->getConfigValue($module, 'legacy')) - { - eFront::isLegacy($this->getConfigValue($module, 'legacy')); - - $url = $this->assemble($request->getRoute(), $request->getRequestParams()); - $request->setRequestInfo($url)->setPathInfo(null)->setRoute(null); - - $_GET = $request->getRequestParams(); - $_SERVER['QUERY_STRING'] = http_build_query($request->getRequestParams(), null, '&'); - - // Infinite loop impossible, as dispatcher will break because of the registered legacy path - $this->route($request); - } - } - - /** - * Convenient way to call config methods - */ - public function configCallback($module, $callBack, $params, $location) - { - if(null == $location) $location = eDispatcher::getModuleConfigLocation($module); - if(!$module || !($obj = eDispatcher::getConfigObject($module, $location))) return false; - - return call_user_func_array(array($obj, $callBack), $params); - } - - /** - * Convert assembled url to shortcode - * - * @param string $route - * @param array $params - * @param array $options {@see eRouter::$_defaultAssembleOptions} - */ - public function assembleSc($route, $params = array(), $options = array()) - { - //if(is_string($options)) parse_str($options, $options); - $url = $this->assemble($route, $params, $options); - return e107::getParser()->createConstants($url, 'mix'); - } - - /** - * Assemble system URL - * Examples: - * assemble('/'); // index page URL e.g. / or /site_folder/ - * $router->assemble('news/view/item?id=1'); // depends on current news config, possible return value is /news/1 - * $router->assemble('*', 'id=1'); // use current request info - /module/controller/action?id=1 - * $router->assemble('* /* /newaction'); // (NO EMPTY SPACES) change only current action - /module/controller/newaction - * $newsItem = array('news_id' => 1, 'news_sef' => 'My Title', ...); // as retrieved from DB - * $router->assemble('news/view/item', $newsItem); // All unused key=>values will be removed and NOT appended as GET vars - * - * @param string $route - * @param array $params - * @param array $options {@see eRouter::$_defaultAssembleOptions} - */ - public function assemble($route, $params = array(), $options = array()) - { - // TODO - url options - $request = eFront::instance()->getRequest(); - if(is_string($options)) parse_str($options, $options); - $options = array_merge($this->_defaultAssembleOptions, $options); - $base = ($options['full'] ? SITEURLBASE : '').$request->getBasePath(); - - $anc = ''; - - - if(is_string($params)) parse_str($params, $params); - if(isset($params['#'])) - { - $anc = '#'.$params['#']; - unset($params['#']); - } - - // Config independent - Deny parameter keys, useful for directly denying sensitive data e.g. password db fields - if(isset($options['deny'])) - { - $list = array_map('trim', explode(',', $options['deny'])); - foreach ($list as $value) - { - unset($params[$value]); - } - unset($list); - } - - // Config independent - allow parameter keys, useful to directly allow data (and not to rely on config allowVars) e.g. when retrieved from db - if(isset($options['allow'])) - { - $list = array_map('trim', explode(',', $options['allow'])); - $_params = $params; - $params = array(); - foreach ($list as $value) - { - if(isset($_params[$value])) $params[$value] = $_params[$value]; - } - unset($list, $_params); - } - - # Optional convenient masks for creating system URL's - if($route === '/' || empty($route)) - { - if($params) - { - $params = $this->createPathInfo($params, $options); - return $base.'?'.$params; - } - return $base; - } - elseif(strpos($route, '?') !== false) - { - $tmp = explode('?', $route, 2); - $route = $tmp[0]; - parse_str($tmp[1], $params); - unset($tmp); - } - - if($route === '*') - { - $route = $route = explode('/', $request->getRoute()); - } - elseif(strpos($route, '*') !== false) - { - $route = explode('/', $route, 3); - if($route[0] === '*') $route[0] = $request->getModule(); - if(isset($route[1]) && $route[1] === '*') $route[1] = $request->getController(); - } - else - { - $route = explode('/', $route, 3); - } - - // we don't know anything about this route, just build it blind - if(!$this->isModule($route[0])) - { - if($params) - { - $params = $this->createPathInfo($params, $options); - return $base.implode('/', $route).'?'.$params; - } - return $base.implode('/', $route); - } - - # fill in index when needed - XXX not needed, may be removed soon - switch (count($route)) - { - case 1: - $route[1] = 'index'; - $route[2] = 'index'; - break; - case 2: - $route[2] = 'index'; - break; - } - - # aliases - $module = $route[0]; - $config = $this->getConfig($module); - - $alias = $this->hasAlias($module, vartrue($options['lan'], null)) ? $this->getAliasFromModule($module, vartrue($options['lan'], null)) : $module; - $route[0] = $alias; - if($options['encode']) $alias = rawurlencode($alias); - - $format = isset($config['format']) && $config['format'] ? $config['format'] : self::FORMAT_GET; - - $urlSuffix = ''; - - // Fix base url for legacy links - if(vartrue($config['noSingleEntry'])) $base = $options['full'] ? SITEURL : e_HTTP; - elseif(self::FORMAT_GET !== $config['format']) - { - $urlSuffix = $this->urlSuffix; - if(isset($config['urlSuffix'])) $urlSuffix = $config['urlSuffix']; - } - - // Create by config callback - if(vartrue($config['selfCreate'])) - { - $tmp = $this->configCallback($module, 'create', array(array($route[1], $route[2]), $params, $options), $config['location']); - - if(empty($tmp)) return '#not-found'; - - if(is_array($tmp)) - { - $route = $tmp[0]; - $params = $tmp[1]; - - if($options['encode']) $route = array_map('rawurlencode', $route); - $route = implode('/', $route); - - if(!$route) - { - $urlSuffix = ''; - if(!$this->isMainModule($module)) $route = $alias; - } - elseif (!$this->isMainModule($module)) - { - $route = $alias.'/'.$route; - } - - } - else - { - // relative url returned - return $base.$tmp.$anc; - } - unset($tmp); - - if($format === self::FORMAT_GET) - { - $params[$this->routeVar] = $route; - $route = ''; - } - - if($params) - { - $params = $this->createPathInfo($params, $options); - return $base.$route.$urlSuffix.'?'.$params.$anc; - } - - return $base.$route.$urlSuffix.$anc; - } - - - // System URL create routine - $rules = $this->getRules($module); - if($format !== self::FORMAT_GET && !empty($rules)) - { - foreach ($rules as $k => $rule) - { - if (($url = $rule->createUrl($this, array($route[1], $route[2]), $params, $options)) !== false) - { - return $base.rtrim(($this->isMainModule($module) ? '' : $alias.'/').$url, '/').$anc; - } - } - } - - // default - module/controller/action - if($this->isMainModule($module)) unset($route[0]); - if($route[2] == 'index') - { - unset($route[2]); - if($route[1] == 'index') unset($route[1]); - } - - # Modify params if required - if($params) - { - if(varset($config['mapVars'])) - { - foreach ($config['mapVars'] as $srcKey => $dstKey) - { - if (isset($params[$srcKey])) - { - $params[$dstKey] = $params[$srcKey]; - unset($params[$srcKey]); - } - } - } - - // false means - no vars are allowed, nothing to preserve here - if(varset($config['allowVars']) === false) $params = array(); - // default empty array value - try to guess what's allowed - mapVars is the best possible candidate - elseif(empty($config['allowVars']) && !empty($config['mapVars'])) $params = array_unique(array_values($config['mapVars'])); - // disallow everything but valid URL parameters - if(!empty($config['allowVars'])) - { - $copy = $params; - $params = array(); - foreach ($config['allowVars'] as $key) - { - if(isset($copy[$key])) $params[$key] = $copy[$key]; - } - unset($copy); - } - - if($format === self::FORMAT_GET) - { - $urlSuffix = ''; - $copy = $params; - $params = array(); - $params[$this->routeVar] = implode('/', $route); - foreach ($copy as $key => $value) - { - $params[$key] = $value; - } - unset($copy); - $route = array(); - } - $params = $this->createPathInfo($params, $options); - $route = implode('/', $route); - if(!$route || $route == $alias) $urlSuffix = ''; - return $base.$route.$urlSuffix.'?'.$params.$anc; - } - $route = implode('/', $route); - if(!$route || $route == $alias) $urlSuffix = ''; - - - return $format === self::FORMAT_GET ? $base.'?'.$this->routeVar.'='.$route.$anc : $base.$route.$urlSuffix.$anc; - } - - /** - * Alias of assemble() - */ - public function url($route, $params = array()) - { - return $this->assemble($route, $params); - } - - /** - * Creates a path info based on the given parameters. - * XXX - maybe we can switch to http_build_query(), should be able to do everything we need in a much better way - * - * @param array $params list of GET parameters - * @param array $options rawurlencode, equal, encode and amp settings - * @param string $key this is used internally for recursive calls - * - * @return string the created path info - */ - public function createPathInfo($params, $options, $key = null) - { - $pairs = array(); - $equal = $options['equal']; - $encode = $options['encode']; - $ampersand = !$encode && $options['amp'] == '&' ? '&' : $options['amp']; - foreach ($params as $k => $v) - { - if (null !== $key) $k = $key.'['.rawurlencode($k).']'; - - if (is_array($v)) $pairs[] = $this->createPathInfo($v, $options, $k); - else - { - if(null === $v) - { - if($encode) - { - $k = null !== $key ? $k : rawurlencode($k); - } - $pairs[] = $k; - continue; - } - if($encode) - { - $k = null !== $key ? $k : rawurlencode($k); - $v = rawurlencode($v); - } - $pairs[] = $k.$equal.$v; - } - } - return implode($ampersand, $pairs); - } - - /** - * Parses a path info into URL segments - * Be sure to not use non-unique chars for equal and ampersand signs, or you'll break your URLs - * - * @param eRequest $request - * @param string $pathInfo path info - * @param string $equal - * @param string $ampersand - */ - public function parsePathInfo($pathInfo, $equal = '/', $ampersand = '/') - { - if ('' === $pathInfo) return; - - if ($equal != $ampersand) $pathInfo = str_replace($equal, $ampersand, $pathInfo); - $segs = explode($ampersand, $pathInfo.$ampersand); - - $segs = explode('/', $pathInfo); - $ret = array(); - - for ($i = 0, $n = count($segs); $i < $n - 1; $i += 2) - { - $key = $segs[$i]; - if ('' === $key) continue; - $value = $segs[$i + 1]; - // array support - if (($pos = strpos($key, '[')) !== false && ($pos2 = strpos($key, ']', $pos + 1)) !== false) - { - $name = substr($key, 0, $pos); - // numerical array - if ($pos2 === $pos + 1) - $ret[$name][] = $value; - // associative array - else - { - $key = substr($key, $pos + 1, $pos2 - $pos - 1); - $ret[$name][$key] = $value; - } - } - else - { - $ret[$key] = $value; - - } - } - return $ret; - } - - /** - * Removes the URL suffix from path info. - * @param string $pathInfo path info part in the URL - * @param string $urlSuffix the URL suffix to be removed - * - * @return string path info with URL suffix removed. - */ - public function removeUrlSuffix($pathInfo, $urlSuffix) - { - if ('' !== $urlSuffix && substr($pathInfo, -strlen($urlSuffix)) === $urlSuffix) return substr($pathInfo, 0, -strlen($urlSuffix)); - else return $pathInfo; - } -} - -class eException extends Exception -{ - -} - -/** - * Based on Yii Framework UrlRule handler - */ -class eUrlRule -{ - /** - * - * For example, ".html" can be used so that the URL looks like pointing to a static HTML page. - * Defaults to null, meaning using the value of {@link cl_shop_core_url::urlSuffix}. - * - * @var string the URL suffix used for this rule. - */ - public $urlSuffix; - - /** - * When this rule is used to parse the incoming request, the values declared in this property - * will be injected into $_GET. - * - * @var array the default GET parameters (name=>value) that this rule provides. - */ - public $defaultParams = array(); - - /** - * @var string module/controller/action - */ - public $route; - - /** - * @var array the mapping from route param name to token name (e.g. _r1=><1>) - */ - public $references = array(); - - /** - * @var string the pattern used to match route - */ - public $routePattern; - - /** - * @var string regular expression used to parse a URL - */ - public $pattern; - - /** - * @var string template used to construct a URL - */ - public $template; - - /** - * @var array list of parameters (name=>regular expression) - */ - public $params = array(); - - /** - * @var boolean whether the URL allows additional parameters at the end of the path info. - */ - public $append; - - /** - * @var array list of SourceKey=>DestinationKey associations - */ - public $mapVars = array(); - - /** - * Numerical array of allowed parameter keys. If set, everything else will be wiped out from the passed parameter array - * @var array - */ - public $allowVars = array(); - - /** - * Should be values matched vs route patterns when assembling URLs - * Warning SLOW when true!!! - * @var mixed true or 1 for preg_match (extremely slower), or 'empty' for only empty check (better) - */ - public $matchValue; - - /** - * Method member of module config object, to be called after successful request parsing - * @var string - */ - public $parseCallback; - - /** - * Shortcode path to the old entry point e.g. '{e_BASE}news.php' - * @var string - */ - public $legacy; - - /** - * Template used for automated recognition of legacy QueryString (parsed via simpleParser with values of retrieved requestParameters) - * @var string - */ - public $legacyQuery; - - /** - * Core regex templates - * Example usage - route will result in - * @var array - */ - public $regexTemplates = array( - 'az' => '[A-Za-z]+', // NOTE - it won't match non-latin word characters! - 'alphanum' => '[\w\pL]+', - 'sefsecure' => '[\w\pL\s\-+.,]+', - 'secure' => '[^\/\'"\\<%]+', - 'number' => '[\d]+', - 'username' => '[\w\pL.\-\s!,]+', // TODO - should equal to username pattern, sync it - 'azOptional' => '[A-Za-z]{0,}', - 'alphanumOptional' => '[\w\pL]{0,}', - 'sefsecureOptional' => '[\w\pL\s\-+.,]{0,}', - 'secureOptional' => '[^\/\'"\\<%]{0,}', - 'numberOptional' => '[\d]{0,}', - 'usernameOptional' => '[\w\pL.\-\s!,]{0,}', // TODO - should equal to username pattern, sync it - ); - - /** - * User defined regex templates - * @var array - */ - public $varTemplates = array(); - - /** - * All regex templates - * @var e_var - */ - protected $_regexTemplates; - - - /** - * Constructor. - * @param string $route the route of the URL (controller/action) - * @param string $pattern the pattern for matching the URL - */ - public function __construct($route, $pattern, $fromCache = false) - { - if (is_array($route)) - { - if ($fromCache && !$pattern) - { - $this->setData($route); - $this->_regexTemplates = new e_vars($this->regexTemplates); - return; - } - - $this->setData($route); - if($this->defaultParams && is_string($this->defaultParams)) - { - parse_str($this->defaultParams, $this->defaultParams); - } - $route = $this->route = $route[0]; - } - else $this->route = $route; - - $tr2['/'] = $tr['/'] = '\\/'; - - if (strpos($route, '<') !== false && preg_match_all('/<(\w+)>/', $route, $matches2)) - { - foreach ($matches2[1] as $name) $this->references[$name] = "<$name>"; - } - - if($this->varTemplates) - { - // don't override core regex templates - $this->regexTemplates = array_merge($this->varTemplates, $this->regexTemplates); - $this->varTemplates = array(); - } - $this->_regexTemplates = new e_vars($this->regexTemplates); - - if (preg_match_all('/<(\w+):?(.*?)?>/', $pattern, $matches)) - { - $tokens = array_combine($matches[1], $matches[2]); - $tp = e107::getParser(); - foreach ($tokens as $name => $value) - { - if ($value === '') $value = '[^\/]+'; - elseif($value[0] == '{') - { - $value = $tp->simpleParse($value, $this->_regexTemplates, '[^\/]+'); - } - $tr["<$name>"] = "(?P<$name>$value)"; - if (isset($this->references[$name])) $tr2["<$name>"] = $tr["<$name>"]; - else $this->params[$name] = $value; - } - } - - $p = rtrim($pattern, '*'); - $this->append = $p !== $pattern; - $p = trim($p, '/'); - $this->template = preg_replace('/<(\w+):?.*?>/', '<$1>', $p); - $this->pattern = '/^'.strtr($this->template, $tr).'\/?'; - if ($this->append) $this->pattern .= '/u'; - else $this->pattern .= '$/u'; - - if ($this->references !== array()) $this->routePattern = '/^'.strtr($this->route, $tr2).'$/u'; - } - - public function getData() - { - $vars = array_keys(get_class_vars(__CLASS__)); - $data = array(); - foreach ($vars as $prop) - { - $data[$prop] = $this->$prop; - } - return $data; - } - - protected function setData($data) - { - if (!is_array($data)) return; - $vars = array_keys(get_class_vars(__CLASS__)); - - foreach ($vars as $prop) - { - if (!isset($data[$prop])) continue; - $this->$prop = $data[$prop]; - } - } - - /** - * Creates a URL based on this rule. - * TODO - more clear logic and flexibility by building the query string - * - * @param eRouter $manager the router/manager - * @param string $route the route - * @param array $params list of parameters - * @param array $options - * @return mixed the constructed URL or false on error - */ - public function createUrl($manager, $route, $params, $options) - { - $case = 'i'; - $ampersand = $options['amp']; - $encode = vartrue($options['encode']); - - if(is_array($route)) $route = implode('/', $route); - - - - $tr = array(); - if ($route !== $this->route) - { - if ($this->routePattern !== null && preg_match($this->routePattern.$case, $route, $matches)) - { - foreach ($this->references as $key => $name) $tr[$name] = $matches[$key]; - } - else return false; - } - - // map vars first - foreach ($this->mapVars as $srcKey => $dstKey) - { - if (isset($params[$srcKey])/* && !isset($params[$dstKey])*/) - { - $params[$dstKey] = $params[$srcKey]; - unset($params[$srcKey]); - } - } - - // false means - no vars are allowed, preserve only route vars - if($this->allowVars === false) $this->allowVars = array_keys($this->params); - // empty array (default) - everything is allowed - - // disallow everything but valid URL parameters - if(!empty($this->allowVars)) - { - $copy = $params; - $params = array(); - $this->allowVars = array_unique(array_merge($this->allowVars, array_keys($this->params))); - foreach ($this->allowVars as $key) - { - if(isset($copy[$key])) $params[$key] = $copy[$key]; - } - unset($copy); - } - - foreach ($this->defaultParams as $key => $value) - { - if (isset($params[$key])) - { - if ($params[$key] == $value) unset($params[$key]); - else return false; - } - } - - foreach ($this->params as $key => $value) if (!isset($params[$key])) return false; - - if($this->matchValue) - { - - if('empty' !== $this->matchValue) - { - foreach($this->params as $key=>$value) - { - if(!preg_match('/'.$value.'/'.$case,$params[$key])) - return false; - } - } - else - { - foreach($this->params as $key=>$value) - { - if(empty($params[$key]) ) - return false; - } - } - } - - $tp = e107::getParser(); - $urlFormat = e107::getConfig()->get('url_sef_translate'); - - foreach ($this->params as $key => $value) - { - // FIX - non-latin URLs proper encoded - $tr["<$key>"] = rawurlencode($params[$key]); //todo transliterate non-latin - // $tr["<$key>"] = eHelper::title2sef($tp->toASCII($params[$key]), $urlFormat); // enabled to test. - unset($params[$key]); - } - - $suffix = $this->urlSuffix === null ? $manager->urlSuffix : $this->urlSuffix; - - // XXX TODO Find better place for this check which will affect all types of SEF URL configurations. (@see news/sef_noid_url.php for duplicate) - - - - - if($urlFormat == 'dashl' || $urlFormat == 'underscorel' || $urlFormat == 'plusl') // convert template to lowercase when using lowercase SEF URL format. - { - $this->template = strtolower($this->template); - } - - $url = strtr($this->template, $tr); - - // Work-around fix for lowercase username - if($urlFormat == 'dashl' && $this->route == 'profile/view') - { - $url = str_replace('%20','-', strtolower($url)); - } - - if(empty($params)) - { - return $url !== '' ? $url.$suffix : $url; - } - - // apppend not supported, maybe in the future...? - if ($this->append) $url .= '/'.$manager->createPathInfo($params, '/', '/').$suffix; - else - { - if ($url !== '') $url = $url.$suffix; - - $options['equal'] = '='; - $url .= '?'.$manager->createPathInfo($params, $options); - } - - - return rtrim($url, '/'); - } - - /** - * Parases a URL based on this rule. - * @param eRouter $manager the router/URL manager - * @param eRequest $request the request object - * @param string $pathInfo path info part of the URL - * @param string $rawPathInfo path info that contains the potential URL suffix - * @return mixed the route that consists of the controller ID and action ID or false on error - */ - public function parseUrl($manager, $request, $pathInfo, $rawPathInfo) - { - $case = 'i'; # 'i' = insensitive - - if ($this->urlSuffix !== null) $pathInfo = $manager->removeUrlSuffix($rawPathInfo, $this->urlSuffix); - - $pathInfo = rtrim($pathInfo, '/').'/'; - // pathInfo is decoded, pattern could be encoded - required for proper url assemble (e.g. cyrillic chars) - if (preg_match(rawurldecode($this->pattern).$case, $pathInfo, $matches)) - { - foreach ($this->defaultParams as $name => $value) - { - //if (!isset($_GET[$name])) $_REQUEST[$name] = $_GET[$name] = $value; - if (!$request->isRequestParam($name)) $request->setRequestParam($name, $value); - } - $tr = array(); - foreach ($matches as $key => $value) - { - if (isset($this->references[$key])) $tr[$this->references[$key]] = $value; - elseif (isset($this->params[$key])) - { - //$_REQUEST[$key] = $_GET[$key] = $value; - $request->setRequestParam($key, $value); - } - } - - if ($pathInfo !== $matches[0]) # Additional GET params exist - { - $manager->parsePathInfo($request, ltrim(substr($pathInfo, strlen($matches[0])), '/')); - } - return (null !== $this->routePattern ? strtr($this->route, $tr) : $this->route); - } - else return false; - } - -} - -abstract class eUrlConfig -{ - /** - * Registered by parse method legacy query string - */ - public $legacyQueryString = null; - - /** - * User defined initialization - */ - public function init() {} - - /** - * Retrieve module config options (including url rules if any) - * Return array is called once and cached, so runtime changes are not an option - * @return array - */ - abstract public function config(); - - /** - * Create URL callback, called only when config option selfParse is set to true - * Expected return array format: - * - * array( - * array(part1, part2, part3), - * array(parm1 => val1, parm2 => val2), - * ); - * - * @param array $route parts - * @param array $params - * @return array|string numerical of type (routeParts, GET Params)| string route or false on error - */ - public function create($route, $params = array(), $options = array()) {} - - /** - * Parse URL callback, called only when config option selfCreate is set to true - * TODO - register variable eURLConfig::currentConfig while initializing the object, remove from method arguments - * @param string $pathInfo - * @param array $params request parameters - * @param eRequest $request - * @param eRouter $router - * @param array $config - * @return string route or false on error - */ - public function parse($pathInfo, $params = array(), eRequest $request = null, eRouter $router = null, $config = array()) - { - return false; - } - - /** - * Legacy callback, used called when config option legacy is not empty - * By default it sets legacy query string to $legacyQueryString value (normaly assigned inside of the parse method) - * @param string $resolvedRoute - * @param eRequest $request - * @param string $callType 'route' - called once, when parsing the request, 'dispatch' - called inside the dispatch loop (in case of controller _forward) - * @param void - */ - public function legacy($resolvedRoute, eRequest $request, $callType = 'route') - { - if($this->legacyQueryString !== null) - { - $request->setLegacyQstring($this->legacyQueryString); - $request->setLegacyPage(); - } - } - - /** - * Developed mainly for legacy modules. - * It should be manually triggered inside of old entry point. The idea is - * to avoid multiple URL addresses having same content (bad SEO practice) - * FIXME - under construction - */ - public function forward() {} - - /** - * Admin interface callback, returns array with all required from administration data - * Return array structure: - * - * array( - * 'name' => 'Module name', - * 'label' => 'Profile Label', - * 'description' => 'Additional profile info, exmples etc.', - * ), - * 'form' => array(), // awaiting future development - * 'callbacks' => array(), // awaiting future development - * ); - * - */ - public function admin() { return array(); } - - /** - * Admin submit hook - * FIXME - under construction - */ - public function submit() {} - - /** - * Admin interface help messages, labels and titles - * FIXME - under construction - */ - public function help() {} - - -} - -/** - * Controller base class, actions are extending it - * - */ -class eController -{ - protected $_request; - protected $_response; - - public function __construct(eRequest $request, eResponse $response = null) - { - $this->setRequest($request) - ->setResponse($response) - ->init(); - } - - /** - * Custom init, always called in the constructor, no matter what is the request dispatch status - */ - public function init() {} - - /** - * Custom shutdown, always called after the controller dispatch, no matter what is the request dispatch status - */ - public function shutdown() {} - - /** - * Pre-action callback, fired only if dispatch status is still true and action method is found - */ - public function preAction() {} - - /** - * Post-action callback, fired only if dispatch status is still true and action method is found - */ - public function postAction() {} - - /** - * @param eRequest $request - * @return eController - */ - public function setRequest($request) - { - $this->_request = $request; - return $this; - } - - /** - * @return eRequest - */ - public function getRequest() - { - return $this->_request; - } - - /** - * @param eResponse $response - * @return eController - */ - public function setResponse($response) - { - $this->_response = $response; - return $this; - } - - /** - * @return eResponse - */ - public function getResponse() - { - return $this->_response; - } - - public function addBody($content) - { - $this->getResponse()->appendBody($content); - return $this; - } - - public function addMetaDescription($description) - { - $this->getResponse()->addMetaDescription($description); - return $this; - } - - /** - * Add document title - * @param string $title - * @param boolean $meta auto-add it as meta-title - * @return eResponse - */ - public function addTitle($title, $meta = true) - { - $this->getResponse()->appendTitle($title); - if($meta) $this->addMetaTitle(strip_tags($title)); - return $this; - } - - - public function addMetaTitle($title) - { - $this->getResponse()->addMetaTitle($title); - return $this; - } - - public function dispatch($actionMethodName) - { - $request = $this->getRequest(); - $content = ''; - - // init() could modify the dispatch status - if($request->isDispatched()) - { - if(method_exists($this, $actionMethodName)) - { - $this->preAction(); - // TODO request userParams() to store private data - check for noPopulate param here - if($request->isDispatched()) - { - $request->populateRequestParams(); - - // allow return output - $content = $this->$actionMethodName(); - if(!empty($content)) $this->addBody($content); - - if($request->isDispatched()) - { - $this->postAction(); - } - } - } - else - { - //TODO not found method by controller or default one - $action = substr($actionMethodName, 6); - throw new eException('Action "'.$action.'" does not exist'); - } - } - $this->shutdown(); - } - - public function run(eRequest $request = null, eResponse $response = null) - { - if(null === $request) $request = $this->getRequest(); - else $this->setRequest($request); - - if(null === $response) $response = $this->getResponse(); - else $this->setResponse($response); - - $action = $request->getActionMethodName(); - - $request->setDispatched(true); - $this->dispatch($action); - - return $this->getResponse(); - } - - protected function _redirect($url, $createURL = false, $code = null) - { - $redirect = e107::getRedirect(); - if($createURL) - { - $url = eFront::instance()->getRouter()->assemble($url, '', 'encode=0'); - } - if(strpos($url, 'http://') !== 0 && strpos($url, 'https://') !== 0) - { - $url = $url[0] == '/' ? SITEURLBASE.$url : SITEURL.$url; - } - $redirect->redirect($url, true, $code); - } - - /** - * System forward - * @param string $route - * @param array $params - */ - protected function _forward($route, $params = array()) - { - $request = $this->getRequest(); - - if(is_string($params)) - { - parse_str($params, $params); - } - - $oldRoute = $request->getRoute(); - $route = explode('/', trim($route, '/')); - - switch (count($route)) { - case 3: - if($route[0] !== '*') $request->setModule($route[0]); - if($route[1] !== '*') $request->setController($route[1]); - $request->setAction($route[2]); - break; - - case 2: - if($route[1] !== '*') $request->setController($route[0]); - $request->setAction($route[1]); - break; - - case 1: - $request->setAction($route[0]); - break; - - default: - return; - break; - } - - $request->addRouteHistory($oldRoute); - - if(false !== $params) $request->setRequestParams($params); - $request->setDispatched(false); - } - - /** - * @param string $methodName - * @param array $args - * @return void - * @throws eException - */ - public function __call($methodName, $args) - { - if ('action' == substr($methodName, 0, 6)) - { - $action = substr($methodName, 6); - throw new eException('Action "'.$action.'" does not exist', 2404); - } - - throw new eException('Method "'.$methodName.'" does not exist', 3404); - } -} - -/** - * @package e107 - * @subpackage e107_handlers - * @version $Id$ - * - * Base front-end controller - */ - -class eControllerFront extends eController -{ - /** - * Plugin name - used to check if plugin is installed - * Set this only if plugin requires installation - * @var string - */ - protected $plugin = null; - - /** - * Default controller access - * @var integer - */ - protected $userclass = e_UC_PUBLIC; - - /** - * Generic 404 page URL (redirect), SITEURL will be added - * @var string - */ - protected $e404 = '404.html'; - - /** - * Generic 403 page URL (redirect), SITEURL will be added - * @var string - */ - protected $e403 = '403.html'; - - /** - * Generic 404 route URL (forward) - * @var string - */ - protected $e404route = 'index/not-found'; - - /** - * Generic 403 route URL (forward) - * @var string - */ - protected $e403route = 'index/access-denied'; - - /** - * View renderer objects - * @var array - */ - protected $_validator; - - /** - * Per action access - * Format 'action' => userclass - * @var array - */ - protected $access = array(); - - /** - * User input filter (_GET) - * Format 'action' => array(var => validationArray) - * @var array - */ - protected $filter = array(); - - /** - * Base constructor - set 404/403 locations - */ - public function __construct(eRequest $request, eResponse $response = null) - { - parent::__construct($request, $response); - $this->_init(); - } - - /** - * Base init, called after the public init() - handle access restrictions - * The base init() method is able to change controller variables on the fly (e.g. access, filters, etc) - */ - final protected function _init() - { - // plugin check - if(null !== $this->plugin) - { - if(!e107::isInstalled($this->plugin)) - { - $this->forward403(); - return; - } - } - - // global controller restriction - if(!e107::getUser()->checkClass($this->userclass, false)) - { - $this->forward403(); - return; - } - - // by action access - if(!$this->checkActionPermissions()) exit; - - // _GET input validation - $this->validateInput(); - - // Set Render mode to module-controller-action, override possible within the action - $this->getResponse()->setRenderMod(str_replace('/', '-', $this->getRequest()->getRoute())); - } - - /** - * Check persmission for current action - * @return boolean - */ - protected function checkActionPermissions() - { - // per action restrictions - $action = $this->getRequest()->getAction(); - if(isset($this->access[$action]) && !e107::getUser()->checkClass($this->access[$action], false)) - { - $this->forward403(); - return false; - } - return true; - } - - public function redirect404() - { - e107::getRedirect()->redirect(SITEURL.$this->e404); - } - - public function redirect403() - { - e107::getRedirect()->redirect(SITEURL.$this->e403); - } - - public function forward404() - { - $this->_forward($this->e404route); - } - - public function forward403() - { - $this->_forward($this->e403route); - } - - /** - * Controller validator object - * @return e_validator - */ - public function getValidator() - { - if(null === $this->_validator) - { - $this->_validator = new e_validator('controller'); - } - - return $this->_validator; - } - - /** - * Register request parameters based on current $filter data (_GET only) - * Additional security layer - */ - public function validateInput() - { - $validator = $this->getValidator(); - $request = $this->getRequest(); - if(empty($this->filter) || !isset($this->filter[$request->getAction()])) return; - $validator->setRules($this->filter[$request->getAction()]) - ->validate($_GET); - - $validData = $validator->getValidData(); - - foreach ($validData as $key => $value) - { - if(!$request->isRequestParam($key)) $request->setRequestParam($key, $value); - } - $validator->clearValidateMessages(); - } - - /** - * System error message proxy - * @param string $message - * @param boolean $session - */ - public function messageError($message, $session = false) - { - return e107::getMessage()->addError($message, 'default', $session); - } - - /** - * System success message proxy - * @param string $message - * @param boolean $session - */ - public function messageSuccess($message, $session = false) - { - return e107::getMessage()->addSuccess($message, 'default', $session); - } - - /** - * System warning message proxy - * @param string $message - * @param boolean $session - */ - public function messageWarning($message, $session = false) - { - return e107::getMessage()->addWarning($message, 'default', $session); - } - - /** - * System debug message proxy - * @param string $message - * @param boolean $session - */ - public function messageDebug($message, $session = false) - { - return e107::getMessage()->addDebug($message, 'default', $session); - } -} - - -/** - * Request handler - * - */ -class eRequest -{ - /** - * @var string - */ - protected $_module; - - /** - * @var string - */ - protected $_controller; - - /** - * @var string - */ - protected $_action; - - /** - * Request status - * @var boolean - */ - protected $_dispatched = false; - - /** - * @var array - */ - protected $_requestParams = array(); - - /** - * @var string - */ - protected $_basePath; - - /** - * @var string - */ - protected $_pathInfo; - - - /** - * @var string - */ - protected $_requestInfo; - - /** - * Pathinfo string used for initial system routing - */ - public $routePathInfo; - - /** - * @var array - */ - protected $_routeHistory = array(); - - /** - * @var boolean if request is already routed - generally set by callbacks to notify router about route changes - */ - public $routed = false; - - /** - * Name of the bootstrap file - * @var string - */ - public $singleEntry = 'index.php'; - - /** - * Request constructor - */ - public function __construct($route = null) - { - if(null !== $route) - { - $this->setRoute($route); - $this->routed = true; - } - } - - /** - * Get system base path - * @return string - */ - public function getBasePath() - { - if(null == $this->_basePath) - { - $this->_basePath = e_HTTP; - if(!e107::getPref('url_disable_pathinfo')) $this->_basePath .= $this->singleEntry.'/'; - } - - return $this->_basePath; - } - - /** - * Set system base path - * @param string $basePath - * @return eRequest - */ - public function setBasePath($basePath) - { - $this->_basePath = $basePath; - return $this; - } - - /** - * Get path info - * If not set, it'll be auto-retrieved - * @return string path info - */ - public function getPathInfo() - { - if(null == $this->_pathInfo) - { - if($this->getBasePath() == $this->getRequestInfo()) - $this->_pathInfo = ''; // map to indexRoute - - else - $this->_pathInfo = substr($this->getRequestInfo(), strlen($this->getBasePath())); - - if($this->_pathInfo && trim($this->_pathInfo, '/') == trim($this->singleEntry, '/')) $this->_pathInfo = ''; - } - - return $this->_pathInfo; - } - - /** - * Override path info - * @param string $pathInfo - * @return eRequest - */ - public function setPathInfo($pathInfo) - { - $this->_pathInfo = $pathInfo; - return $this; - } - - /** - * @return string request info - */ - public function getRequestInfo() - { - if(null === $this->_requestInfo) - { - $this->_requestInfo = e_REQUEST_HTTP; - } - return $this->_requestInfo; - } - - - /** - * Override request info - * @param string $pathInfo - * @return eRequest - */ - public function setRequestInfo($requestInfo) - { - $this->_requestInfo = $requestInfo; - return $this; - } - - /** - * Quick front page check - */ - public static function isFrontPage($entryScript = 'index.php', $currentPathInfo = e_REQUEST_HTTP) - { - $basePath = e_HTTP; - if(!e107::getPref('url_disable_pathinfo')) $basePath .= $entryScript.'/'; - - return ($basePath == $currentPathInfo); - } - - /** - * Get current controller string - * @return string - */ - public function getController() - { - return $this->_controller; - } - - /** - * Get current controller name - * Example: requested controller-name or 'controller name' -> converted to controller_name - * @return string - */ - public function getControllerName() - { - return eHelper::underscore($this->_controller); - } - - /** - * Set current controller name - * Example: controller_name OR 'controller name' -> converted to controller-name - * Always sanitized - * @param string $controller - * @return eRequest - */ - public function setController($controller) - { - $this->_controller = strtolower(eHelper::dasherize($this->sanitize($controller))); - return $this; - } - - /** - * Get current module string - * @return string - */ - public function getModule() - { - return $this->_module; - } - - /** - * Get current module name - * Example: module-name OR 'module name' -> converted to module_name - * @return string - */ - public function getModuleName() - { - return eHelper::underscore($this->_module); - } - - /** - * Set current module name - * Example: module_name OR 'module name' -> converted to module-name - * Always sanitized - * @param string $module - * @return eRequest - */ - public function setModule($module) - { - $this->_module = strtolower(eHelper::dasherize($this->sanitize($module))); - return $this; - } - - /** - * Get current action string - * @return string - */ - public function getAction() - { - return $this->_action; - } - - /** - * Get current action name - * Example: action-name OR 'action name' OR action_name -> converted to ActionName - * @return string - */ - public function getActionName() - { - return eHelper::camelize($this->_action, true); - } - - /** - * Get current action method name - * Example: action-name OR 'action name' OR action_name -> converted to actionActionName - * @return string - */ - public function getActionMethodName() - { - return 'action'.eHelper::camelize($this->_action, true); - } - - /** - * Set current action name - * Example: action_name OR 'action name' OR Action_Name OR 'Action Name' -> converted to ation-name - * Always sanitized - * @param string $action - * @return eRequest - */ - public function setAction($action) - { - $this->_action = strtolower(eHelper::dasherize($this->sanitize($action))); - return $this; - } - - /** - * Get current route string/array -> module/controller/action - * @param boolean $array - * @return string|array route - */ - public function getRoute($array = false) - { - if(!$this->getModule()) - { - $route = array('index', 'index', 'index'); - } - else - { - $route = array( - $this->getModule(), - $this->getController() ? $this->getController() : 'index', - $this->getAction() ? $this->getAction() : 'index', - ); - } - return ($array ? $route : implode('/', $route)); - } - - /** - * Set current route - * @param string $route module/controller/action - * @return eRequest - */ - public function setRoute($route) - { - if(null === $route) - { - $this->_module = null; - $this->_controller = null; - $this->_action = null; - } - return $this->initFromRoute($route); - } - - /** - * System routing track, used in controllers forwarder - * @param string $route - * @return eRequest - */ - public function addRouteHistory($route) - { - $this->_routeHistory[] = $route; - return $this; - } - - /** - * Retrieve route from history track - * Based on $source we can retrieve - * - array of all history records - * - 'first' route record - * - 'last' route record - * - history record by its index number - * @param mixed $source - * @return string|array - */ - public function getRouteHistory($source = null) - { - if(null === $source) return $this->_routeHistory; - - if(!$this->_routeHistory) return null; - elseif('last' === $source) - { - return $this->_routeHistory[count($this->_routeHistory) -1]; - } - elseif('first' === $source) - { - return $this->_routeHistory[0]; - } - elseif(is_int($source)) - { - return isset($this->_routeHistory[$source]) ? $this->_routeHistory[$source] : null; - } - return null; - } - - /** - * Search route history for the given $route - * - * @param string $route - * @return integer route index or false if not found - */ - public function findRouteHistory($route) - { - return array_search($route, $this->_routeHistory); - } - - /** - * Populate module, controller and action from route string - * @param string $route - * @return array route data - */ - public function initFromRoute($route) - { - $route = trim($route, '/'); - if(!$route) - { - $route = 'index/index/index'; - } - $parts = explode('/', $route); - $this->setModule($parts[0]) - ->setController(vartrue($parts[1], 'index')) - ->setAction(vartrue($parts[2], 'index')); - - return $this;//->getRoute(true); - } - - /** - * Get request parameter - * @param string $key - * @param string $default value if key not set - * @return mixed value - */ - public function getRequestParam($key, $default = null) - { - return (isset($this->_requestParams[$key]) ? $this->_requestParams[$key] : $default); - } - - /** - * Check if request parameter exists - * @param string $key - * @return boolean - */ - public function isRequestParam($key) - { - return isset($this->_requestParams[$key]); - } - - /** - * Get request parameters array - * @return array value - */ - public function getRequestParams() - { - return $this->_requestParams; - } - - /** - * Set request parameter - * @param string $key - * @param mixed $value - * @return eRequest - */ - public function setRequestParam($key, $value) - { - $this->_requestParams[$key] = $value; - return $this; - } - - /** - * Set request parameters - * @param array $params - * @return eRequest - */ - public function setRequestParams($params) - { - $this->_requestParams = $params; - return $this; - } - - /** - * Populate current request parameters (_GET scope) - * @return eRequest - */ - public function populateRequestParams() - { - $rp = $this->getRequestParams(); - - foreach ($rp as $key => $value) - { - $_GET[$key] = $value; - } - return $this; - } - - /** - * More BC - * @param string $qstring - * @return eRequest - */ - public function setLegacyQstring($qstring = null) - { - if(defined('e_QUERY')) return $this; - - if(null === $qstring) - { - $qstring = self::getQueryString(); - } - - if(!defined('e_SELF')) - { - define("e_SELF", e_REQUEST_SELF); - } - - if(!defined('e_QUERY')) - { - define("e_QUERY", $qstring); - } - - $_SERVER['QUERY_STRING'] = e_QUERY; - - if(strpos(e_QUERY,"=")!==false ) // Fix for legacyQuery using $_GET ie. ?x=y&z=1 etc. - { - parse_str(str_replace(array('&'), array('&'), e_QUERY),$tmp); - foreach($tmp as $key=>$value) - { - $_GET[$key] = $value; - } - } - - return $this; - } - - /** - * And More BC :/ - * @param string $page - * @return eRequest - */ - public function setLegacyPage($page = null) - { - if(defined('e_PAGE')) return $this; - if(null === $page) - { - $page = eFront::isLegacy(); - } - if(!$page) - { - define('e_PAGE', $this->singleEntry); - } - else define('e_PAGE', basename(str_replace(array('{', '}'), '/', $page))); - return $this; - } - - /** - * And More from the same - BC :/ - * @return string - */ - public static function getQueryString() - { - $qstring = ''; - if($_SERVER['QUERY_STRING']) - { - $qstring = str_replace(array('{', '}', '%7B', '%7b', '%7D', '%7d'), '', rawurldecode($_SERVER['QUERY_STRING'])); - } - $qstring = str_replace('&', '&', e107::getParser()->post_toForm($qstring)); - return $qstring; - } - - /** - * Basic sanitize method for module, controller and action input values - * @param string $str string to be sanitized - * @param string $pattern optional replace pattern - * @param string $replace optional replace string, defaults to dash - */ - public function sanitize($str, $pattern='', $replace='-') - { - if (!$pattern) $pattern = '/[^\w\pL-]/u'; - - return preg_replace($pattern, $replace, $str); - } - - /** - * Set dispatched status of the request - * @param boolean $mod - * @return eRequest - */ - public function setDispatched($mod) - { - $this->_dispatched = $mod ? true : false; - return $this; - } - - /** - * Get dispatched status of the request - * @return boolean - */ - public function isDispatched() - { - return $this->_dispatched; - } -} - -class eResponse -{ - protected $_body = array('default' => ''); - protected $_title = array('default' => array()); - protected $_e_PAGETITLE = array(); - protected $_META_DESCRIPTION = array(); - protected $_META_KEYWORDS = array(); - protected $_render_mod = array('default' => 'default'); - protected $_meta_title_separator = ' - '; - protected $_meta_name_only = array('keywords', 'viewport'); // Keep FB happy. - protected $_meta_property_only = array('article:section', 'article:tag'); // Keep FB happy. - protected $_meta = array(); - protected $_title_separator = ' » '; - protected $_content_type = 'html'; - protected $_content_type_arr = array( - 'html' => 'text/html', - 'css' => 'text/css', - 'xml' => 'text/xml', - 'json' => 'application/json', - 'js' => 'application/javascript', - 'rss' => 'application/rss+xml', - 'soap' => 'application/soap+xml', - ); - - protected $_params = array( - 'render' => true, - 'meta' => false, - 'jsonNoTitle' => false, - 'jsonRender' => false, - ); - - public function setParam($key, $value) - { - $this->_params[$key] = $value; - return $this; - } - - public function setParams($params) - { - $this->_params = $params; - return $this; - } - - public function getParam($key, $default = null) - { - return (isset($this->_params[$key]) ? $this->_params[$key] : $default); - } - - public function isParam($key) - { - return isset($this->_params[$key]); - } - - public function addContentType($typeName, $mediaType) - { - $this->_content_type_arr[$typeName] = $mediaType; - return $this; - } - - public function getContentType() - { - return $this->_content_type; - } - - public function getContentMediaType($typeName) - { - if(isset($this->_content_type_arr[$typeName])) - return $this->_content_type_arr[$typeName]; - } - - public function setContentType($typeName) - { - $this->_content_type = $typeName; - } - - /** - * @return eResponse - */ - public function sendContentType() - { - $ctypeStr = $this->getContentMediaType($this->getContentType()); - if($ctypeStr) - { - header('Content-type: '.$this->getContentMediaType($this->getContentType()).'; charset=utf-8', TRUE); - } - return $this; - } - - /** - * @return eResponse - */ - public function addHeader($header, $override = false, $responseCode = null) - { - header($header, $override, $responseCode); - return $this; - } - - /** - * Append content - * @param str $body - * @param str $ns namespace - * @return eResponse - */ - public function appendBody($body, $ns = 'default') - { - if(!isset($this->_body[$ns])) - { - $this->_body[$ns] = ''; - } - $this->_body[$ns] .= $body; - - return $this; - } - - /** - * Set content - * @param str $body - * @param str $ns namespace - * @return eResponse - */ - public function setBody($body, $ns = 'default') - { - $this->_body[$ns] = $body; - return $this; - } - - - /** - * @param $name - * @param $content - * @return $this - */ - public function setMeta($name, $content) - { - foreach($this->_meta as $k=>$v) - { - if($v['name'] === $name) - { - $this->_meta[$k]['content'] = $content; - } - } - - return $this; - - } - - - /** - * Removes a Meta tag by name/property. - * - * @param string $name - * 'name' or 'property' for the meta tag we want to remove. - * - * @return eResponse $this - */ - public function removeMeta($name) - { - foreach($this->_meta as $k=>$v) - { - // Meta tags like: - if(isset($v['name']) && $v['name'] === $name) - { - unset($this->_meta[$k]); - continue; - } - - // Meta tags like: - if(isset($v['property']) && $v['property'] === $name) - { - unset($this->_meta[$k]); - } - } - - return $this; - } - - - /** - * Prepend content - * @param str $body - * @param str $ns namespace - * @return eResponse - */ - function prependBody($body, $ns = 'default') - { - if(!isset($this->_body[$ns])) - { - $this->_body[$ns] = ''; - } - $this->_body[$ns] = $content.$this->_body[$ns]; - - return $this; - } - - /** - * Get content - * @param string $ns - * @param boolean $reset - * @return string - */ - public function getBody($ns = 'default', $reset = false) - { - if(!isset($this->_body[$ns])) - { - $this->_body[$ns] = ''; - } - $ret = $this->_body[$ns]; - if($reset) unset($this->_body[$ns]); - - return $ret; - } - - /** - * @param string $title - * @param string $ns - * @return eResponse - */ - function setTitle($title, $ns = 'default') - { - - if(!is_string($ns) || empty($ns)) - { - $this->_title['default'] = array((string) $title); - } - else - { - $this->_title[$ns] = array((string) $title); - } - return $this; - } - - /** - * @param string $title - * @param string $ns - * @return eResponse - */ - function appendTitle($title, $ns = 'default') - { - if(empty($title)) - { - return $this; - } - if(!is_string($ns) || empty($ns)) - { - $ns = 'default'; - } - elseif(!isset($this->_title[$ns])) - { - $this->_title[$ns] = array(); - } - $this->_title[$ns][] = (string) $title; - return $this; - } - - /** - * @param string $title - * @param string $ns - * @return eResponse - */ - function prependTitle($title, $ns = 'default') - { - if(empty($title)) - { - return $this; - } - if(!is_string($ns) || empty($ns)) - { - $ns = 'default'; - } - elseif(!isset($this->_title[$ns])) - { - $this->_title[$ns] = array(); - } - array_unshift($this->_title[$ns], $title); - return $this; - } - - /** - * Assemble title - * @param string $ns - * @param bool $reset - * @return string - */ - function getTitle($ns = 'default', $reset = false) - { - if(!is_string($ns) || empty($ns)) - { - $ret = implode($this->_title_separator, $this->_title['default']); - if($reset) - $this->_title['default'] = ''; - } - elseif(isset($this->_title[$ns])) - { - $ret = implode($this->_title_separator, $this->_title[$ns]); - if($reset) - unset($this->_title[$ns]); - } - else - { - $ret = ''; - } - return $ret; - } - - /** - * - * @param string $render_mod - * @param mixed $ns - * @return eResponse - */ - function setRenderMod($render_mod, $ns = 'default') - { - $this->_render_mod[$ns] = $render_mod; - return $this; - } - - /** - * Retrieve render mod - * @param mixed $ns - * @return mixed - */ - function getRenderMod($ns = 'default') - { - if(!is_string($ns) || empty($ns)) - { - $ns = 'default'; - } - return vartrue($this->_render_mod[$ns], null); - } - - /** - * Generic meta information - * Example usage: - * addMeta('og:title', 'My Title'); - * addMeta(null, 30, array('http-equiv' => 'refresh')); - * addMeta(null, null, array('http-equiv' => 'refresh', 'content' => 30)); // same as above - * @param string $name 'name' attribute value, or null to avoid it - * @param string $content 'content' attribute value, or null to avoid it - * @param array $extended format 'attribute_name' => 'value' - * @return eResponse - */ - public function addMeta($name = null, $content = null, $extended = array()) - { - if(empty($content)){ return $this; } // content is required, otherwise ignore. - - //TODO need an option that allows subsequent entries to overwrite existing ones. - //ie. 'description' and 'keywords' should never be duplicated, but overwritten by plugins and other non-pref-based meta data. - - $attr = array(); - - if(null !== $name) - { - // $key = (substr($name,0,3) == 'og:') ? 'property' : 'name'; - // $attr[$key] = $name; - if(!in_array($name, $this->_meta_name_only)) - { - $attr['property'] = $name; // giving both should be valid and avoid issues with FB and others. - } - - if(!in_array($name, $this->_meta_property_only)) - { - $attr['name'] = $name; - } - } - - - - if(null !== $content) $attr['content'] = $content; - if(!empty($extended)) - { - if(!empty($attr)) $attr = array_merge($attr, $extended); - else $attr = $extended; - } - - if(!empty($attr)) $this->_meta[] = $attr; - return $this; - } - - /** - * Render meta tags, registered via addMeta() method - * @return string - */ - public function renderMeta() - { - $attrData = ''; - - e107::getEvent()->trigger('system_meta_pre', $this->_meta); - - foreach ($this->_meta as $attr) - { - $attrData .= ' $v) - { - $attrData .= ' '.preg_replace('/[^\w\-]/', '', $p).'="'.str_replace(array('"', '<'), '', $v).'"'; - } - $attrData .= ' />'."\n"; - } - - return $attrData; - } - - /** - * Add meta title, description and keywords - * - * @param string $meta property name - * @param string $content meta content - * @return eResponse - */ - function addMetaData($meta, $content) - { - $meta = '_' . $meta; - if(isset($this->$meta) && !empty($content)) - { - $content = str_replace(array('&', '"', "'"), array('&', '', ''), $content); - $this->{$meta}[] = htmlspecialchars((string) $content, ENT_QUOTES, 'UTF-8'); - } - return $this; - } - - /** - * Get meta title, description and keywords - * - * @param string $meta property name - * @return string - */ - function getMetaData($meta, $separator = '') - { - $meta = '_' . $meta; - if(isset($this->$meta) && !empty($this->$meta)) - { - return implode($separator, $this->$meta); - } - return ''; - } - - - - /** - * Return an array of all meta data - * @return array - */ - function getMeta() - { - return $this->_meta; - } - - - /** - * @param string $title - * @return eResponse - */ - function addMetaTitle($title) - { - return $this->addMetaData('e_PAGETITLE', $title); - } - - function getMetaTitle() - { - return $this->getMetaData('e_PAGETITLE', $this->_meta_title_separator); - } - - /** - * @param string $description - * @return eResponse - */ - function addMetaDescription($description) - { - return $this->addMetaData('META_DESCRIPTION', $description); - } - - function getMetaDescription() - { - return $this->getMetaData('META_DESCRIPTION'); - } - - /** - * @param string $keywords - * @return eResponse - */ - function addMetaKeywords($keywords) - { - return $this->addMetaData('META_KEYWORDS', $keywords); - } - - function getMetaKeywords() - { - return $this->getMetaData('META_KEYWORDS', ','); - } - - /** - * Send e107 meta-data - * @return eResponse - */ - function sendMeta() - { - //HEADERF already included or meta content already sent - if(e_AJAX_REQUEST || defined('USER_AREA') || defined('e_PAGETITLE')) - return $this; - - if(!defined('e_PAGETITLE') && !empty($this->_e_PAGETITLE)) - { - define('e_PAGETITLE', $this->getMetaTitle()); - } - if(!defined('META_DESCRIPTION') && !empty($this->_META_DESCRIPTION)) - { - define('META_DESCRIPTION', $this->getMetaDescription()); - } - if(!defined('META_KEYWORDS') && !empty($this->_META_KEYWORDS)) - { - define('META_KEYWORDS', $this->getMetaKeywords()); - } - return $this; - } - - /** - * Send Response Output - default method - * TODO - ajax send, using js_manager - * @param string $ns namespace/segment - * @param bool $return - * @param bool $render_message append system messages - * @return null|string - */ - function send($ns = null, $return = true, $render_message = true) - { - $content = $this->getBody($ns, true); - $render = $this->getParam('render'); - $meta = $this->getParam('meta'); - - $this->sendContentType(); - - if($render_message) - { - $content = eMessage::getInstance()->render().$content; - } - - if($meta) - { - $this->sendMeta(); - } - - //render disabled by the controller - if(!$this->getRenderMod($ns)) - { - $render = false; - } - - if($render) - { - $render = e107::getRender(); - if($return) - { - return $render->tablerender($this->getTitle($ns, true), $content, $this->getRenderMod($ns), true); - } - else - { - $render->tablerender($this->getTitle($ns, true), $content, $this->getRenderMod($ns)); - return ''; - } - } - elseif($return) - { - return $content; - } - else - { - print $content; - return ''; - } - } - - /** - * Send AJAX Json Response Output - default method - * It's fully compatible with the core dialog.js - * @param array $override override output associative array (header, body and footer keys) - * @param string $ns namespace/segment - * @param bool $render_message append system messages - */ - function sendJson($override = array(), $ns = null, $render_message = true) - { - if(!$ns) $ns = 'default'; - - $content = $this->getBody($ns, true); - // separate render parameter for json response, false by default - $render = $this->getParam('jsonRender'); - if($render_message) - { - $content = eMessage::getInstance()->render().$content; - } - - //render disabled by the controller - if(!$this->getRenderMod($ns)) - { - $render = false; - } - - - $title = ''; - if(!$this->getParam('jsonNoTitle')) - { - $titleArray = $this->_title; - $title = isset($titleArray[$ns]) ? array_pop($titleArray[$ns]) : ''; - } - - if($render) - { - $render = e107::getRender(); - $content = $render->tablerender($this->getTitle($ns, true), $content, $this->getRenderMod($ns), true); - } - - $jshelper = e107::getJshelper(); - $override = array_merge(array( - 'header' => $title, - 'body' => $content, - 'footer' => $statusText, - ), $override); - echo $jshelper->buildJsonResponse($override); - $jshelper->sendJsonResponse(null); - } - - /** - * JS manager - * @return e_jsmanager - */ - function getJs() - { - return e107::getJs(); - } -} - -/** - * We move all generic helper functionallity here - a lot of candidates in e107 class - * - */ -class eHelper -{ - protected static $_classRegEx = '#[^\w\s\-]#'; - protected static $_idRegEx = '#[^\w\-]#'; - protected static $_styleRegEx = '#[^\w\s\-\.;:!]#'; - - public static function secureClassAttr($string) - { - return preg_replace(self::$_classRegEx, '', $string); - } - - public static function secureIdAttr($string) - { - $string = str_replace(array('/','_'),'-',$string); - return preg_replace(self::$_idRegEx, '', $string); - } - - public static function secureStyleAttr($string) - { - return preg_replace(self::$_styleRegEx, '', $string); - } - - public static function buildAttr($safeArray) - { - return http_build_query($safeArray, null, '&'); - } - - public static function formatMetaTitle($title) - { - $title = trim(str_replace(array('"', "'"), '', strip_tags(e107::getParser()->toHTML($title, TRUE)))); - return trim(preg_replace('/[\s,]+/', ' ', str_replace('_', ' ', $title))); - } - - public static function secureSef($sef) - { - return trim(preg_replace('/[^\w\pL\s\-+.,]+/u', '', strip_tags(e107::getParser()->toHTML($sef, TRUE)))); - } - - public static function formatMetaKeys($keywordString) - { - $keywordString = preg_replace('/[^\w\pL\s\-.,+]/u', '', strip_tags(e107::getParser()->toHTML($keywordString, TRUE))); - return trim(preg_replace('/[\s]?,[\s]?/', ',', str_replace('_', ' ', $keywordString))); - } - - public static function formatMetaDescription($descrString) - { - $descrString = preg_replace('/[\r]*\n[\r]*/', ' ', trim(str_replace(array('"', "'"), '', strip_tags(e107::getParser()->toHTML($descrString, TRUE))))); - return trim(preg_replace('/[\s]+/', ' ', str_replace('_', ' ', $descrString))); - } - - /** - * Convert title to valid SEF URL string - * Type ending with 'l' stands for 'to lowercase', ending with 'c' - 'to camel case' - * @param string $title - * @param string $type dashl|dashc|dash|underscorel|underscorec|underscore|plusl|plusc|plus|none - * @return mixed|string - */ - public static function title2sef($title, $type = null) - { - /*$char_map = array( - // Latin - 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A', 'Æ' => 'AE', 'Ç' => 'C', - 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', - 'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => 'O', 'Ő' => 'O', - 'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ű' => 'U', 'Ý' => 'Y', 'Þ' => 'TH', - 'ß' => 'ss', - 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 'å' => 'a', 'æ' => 'ae', 'ç' => 'c', - 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', - 'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ő' => 'o', - 'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ü' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th', - 'ÿ' => 'y', - // Latin symbols - '©' => '(c)', - // Greek - 'Α' => 'A', 'Β' => 'B', 'Γ' => 'G', 'Δ' => 'D', 'Ε' => 'E', 'Ζ' => 'Z', 'Η' => 'H', 'Θ' => '8', - 'Ι' => 'I', 'Κ' => 'K', 'Λ' => 'L', 'Μ' => 'M', 'Ν' => 'N', 'Ξ' => '3', 'Ο' => 'O', 'Π' => 'P', - 'Ρ' => 'R', 'Σ' => 'S', 'Τ' => 'T', 'Υ' => 'Y', 'Φ' => 'F', 'Χ' => 'X', 'Ψ' => 'PS', 'Ω' => 'W', - 'Ά' => 'A', 'Έ' => 'E', 'Ί' => 'I', 'Ό' => 'O', 'Ύ' => 'Y', 'Ή' => 'H', 'Ώ' => 'W', 'Ϊ' => 'I', - 'Ϋ' => 'Y', - 'α' => 'a', 'β' => 'b', 'γ' => 'g', 'δ' => 'd', 'ε' => 'e', 'ζ' => 'z', 'η' => 'h', 'θ' => '8', - 'ι' => 'i', 'κ' => 'k', 'λ' => 'l', 'μ' => 'm', 'ν' => 'n', 'ξ' => '3', 'ο' => 'o', 'π' => 'p', - 'ρ' => 'r', 'σ' => 's', 'τ' => 't', 'υ' => 'y', 'φ' => 'f', 'χ' => 'x', 'ψ' => 'ps', 'ω' => 'w', - 'ά' => 'a', 'έ' => 'e', 'ί' => 'i', 'ό' => 'o', 'ύ' => 'y', 'ή' => 'h', 'ώ' => 'w', 'ς' => 's', - 'ϊ' => 'i', 'ΰ' => 'y', 'ϋ' => 'y', 'ΐ' => 'i', - // Turkish - 'Ş' => 'S', 'İ' => 'I', 'Ç' => 'C', 'Ü' => 'U', 'Ö' => 'O', 'Ğ' => 'G', - 'ş' => 's', 'ı' => 'i', 'ç' => 'c', 'ü' => 'u', 'ö' => 'o', 'ğ' => 'g', - // Russian - 'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'Yo', 'Ж' => 'Zh', - 'З' => 'Z', 'И' => 'I', 'Й' => 'J', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O', - 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C', - 'Ч' => 'Ch', 'Ш' => 'Sh', 'Щ' => 'Sh', 'Ъ' => '', 'Ы' => 'Y', 'Ь' => '', 'Э' => 'E', 'Ю' => 'Yu', - 'Я' => 'Ya', - 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'yo', 'ж' => 'zh', - 'з' => 'z', 'и' => 'i', 'й' => 'j', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o', - 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c', - 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sh', 'ъ' => '', 'ы' => 'y', 'ь' => '', 'э' => 'e', 'ю' => 'yu', - 'я' => 'ya', - // Ukrainian - 'Є' => 'Ye', 'І' => 'I', 'Ї' => 'Yi', 'Ґ' => 'G', - 'є' => 'ye', 'і' => 'i', 'ї' => 'yi', 'ґ' => 'g', - // Czech - 'Č' => 'C', 'Ď' => 'D', 'Ě' => 'E', 'Ň' => 'N', 'Ř' => 'R', 'Š' => 'S', 'Ť' => 'T', 'Ů' => 'U', - 'Ž' => 'Z', - 'č' => 'c', 'ď' => 'd', 'ě' => 'e', 'ň' => 'n', 'ř' => 'r', 'š' => 's', 'ť' => 't', 'ů' => 'u', - 'ž' => 'z', - // Polish - 'Ą' => 'A', 'Ć' => 'C', 'Ę' => 'e', 'Ł' => 'L', 'Ń' => 'N', 'Ó' => 'o', 'Ś' => 'S', 'Ź' => 'Z', - 'Ż' => 'Z', - 'ą' => 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n', 'ó' => 'o', 'ś' => 's', 'ź' => 'z', - 'ż' => 'z', - // Latvian - 'Ā' => 'A', 'Č' => 'C', 'Ē' => 'E', 'Ģ' => 'G', 'Ī' => 'i', 'Ķ' => 'k', 'Ļ' => 'L', 'Ņ' => 'N', - 'Š' => 'S', 'Ū' => 'u', 'Ž' => 'Z', - 'ā' => 'a', 'č' => 'c', 'ē' => 'e', 'ģ' => 'g', 'ī' => 'i', 'ķ' => 'k', 'ļ' => 'l', 'ņ' => 'n', - 'š' => 's', 'ū' => 'u', 'ž' => 'z' - );*/ - - $tp = e107::getParser(); - - // issue #3245: strip all html and bbcode before processing - $title = $tp->toText($title); - - $title = $tp->toASCII($title); - - $title = str_replace(array('/',' ',","),' ',$title); - $title = str_replace(array("&","(",")"),'',$title); - $title = preg_replace('/[^\w\d\pL\s.-]/u', '', strip_tags(e107::getParser()->toHTML($title, TRUE))); - $title = trim(preg_replace('/[\s]+/', ' ', str_replace('_', ' ', $title))); - $title = str_replace(array(' - ',' -','- ','--'),'-',$title); // cleanup to avoid --- - - $words = str_word_count($title,1, '1234567890'); - - $limited = array_slice($words, 0, 14); // Limit number of words to 14. - any more and it ain't friendly. - - $title = implode(" ",$limited); - - if(null === $type) - { - $type = e107::getPref('url_sef_translate'); - } - - switch ($type) - { - case 'dashl': //dasherize, to lower case - return self::dasherize($tp->ustrtolower($title)); - break; - - case 'dashc': //dasherize, camel case - return self::dasherize(self::camelize($title, true, ' ')); - break; - - case 'dash': //dasherize - return self::dasherize($title); - break; - - case 'underscorel': ///underscore, to lower case - return self::underscore($tp->ustrtolower($title)); - break; - - case 'underscorec': ///underscore, camel case - return self::underscore(self::camelize($title, true, ' ')); - break; - - case 'underscore': ///underscore - return self::underscore($title); - break; - - case 'plusl': ///plus separator, to lower case - return str_replace(' ', '+', $tp->ustrtolower($title)); - break; - - case 'plusc': ///plus separator, to lower case - return str_replace(' ', '+', self::camelize($title, true, ' ')); - break; - - case 'plus': ///plus separator - return str_replace(' ', '+', $title); - break; - - case 'none': - default: - return $title; - break; - } - } - - /** - * Return a memory value formatted helpfully - * $dp overrides the number of decimal places displayed - realistically, only 0..3 are sensible - * FIXME e107->parseMemorySize() START - * - move here all e107 class ban/ip related methods - * - out of (integer) range case? - * 32 bit systems range: -2147483648 to 2147483647 - * 64 bit systems range: -9223372036854775808 9223372036854775807 - * {@link http://www.php.net/intval} - * FIXME e107->parseMemorySize() END - * - * @param integer $size - * @param integer $dp - * @return string formatted size - */ - public static function parseMemorySize($size, $dp = 2) - { - if (!$size) { $size = 0; } - if ($size < 4096) - { // Fairly arbitrary limit below which we always return number of bytes - return number_format($size, 0).CORE_LAN_B; - } - - $size = $size / 1024; - $memunit = CORE_LAN_KB; - - if ($size > 1024) - { /* 1.002 mb, etc */ - $size = $size / 1024; - $memunit = CORE_LAN_MB; - } - if ($size > 1024) - { /* show in GB if >1GB */ - $size = $size / 1024; - $memunit = CORE_LAN_GB; - } - if ($size > 1024) - { /* show in TB if >1TB */ - $size = $size / 1024; - $memunit = CORE_LAN_TB; - } - return (number_format($size, $dp).$memunit); - } - - /** - * Get the current memory usage of the code - * If $separator argument is null, raw data (array) will be returned - * - * @param null|string $separator - * @return string|array memory usage - */ - public static function getMemoryUsage($separator = '/') - { - $ret = array(); - if(function_exists("memory_get_usage")) - { - $ret[] = eHelper::parseMemorySize(memory_get_usage()); - // With PHP>=5.2.0, can show peak usage as well - if (function_exists("memory_get_peak_usage")) $ret[] = eHelper::parseMemorySize(memory_get_peak_usage(TRUE)); - } - else - { - $ret[] = 'Unknown'; - } - - return (null !== $separator ? implode($separator, $ret) : $ret); - } - - public static function camelize($str, $all = false, $space = '') - { - // clever recursion o.O - if($all) return self::camelize('-'.$str, false, $space); - - $tmp = explode('-', str_replace(array('_', ' '), '-', e107::getParser()->ustrtolower($str))); - return trim(implode($space, array_map('ucfirst', $tmp)), $space); - } - - public static function labelize($str, $space = ' ') - { - return self::camelize($str, true, ' '); - } - - public static function dasherize($str) - { - return str_replace(array('_', ' '), '-', $str); - } - - public static function underscore($str) - { - return str_replace(array('-', ' '), '_', $str); - } - - /** - * Parse generic shortcode parameter string - * Format expected: {SC=key=val&key1=val1...} - * Escape strings: \& => & - * - * @param string $parmstr - * @return array associative param array - */ - public static function scParams($parm) - { - if (!$parm) return array(); - if (!is_array($parm)) - { - $parm = str_replace('\&', '%%__amp__%%', $parm); - $parm = str_replace('&', '&', $parm); // clean when it comes from the DB - parse_str($parm, $parm); - foreach ($parm as $k => $v) - { - $parm[str_replace('%%__amp__%%', '&', $k)] = str_replace('%%__amp__%%', '\&', $v); - } - } - - return $parm; - } - - /** - * Parse shortcode parameter string of type 'dual parameters' - advanced, more complex and slower(!) case - * Format expected: {SC=name|key=val&key1=val1...} - * Escape strings: \| => | , \& => & and \& => & - * Return array is formatted like this: - * 1 => string|array (depends on $name2array value) containing first set of parameters; - * 2 => array containing second set of parameters; - * 3 => string containing second set of parameters; - * - * @param string $parmstr - * @param boolean $first2array If true, first key (1) of the returned array will be parsed to array as well - * @return array - */ - public static function scDualParams($parmstr, $first2array = false) - { - if (!$parmstr) return array(1 => '', 2 => array(), 3 => ''); - if (is_array($parmstr)) return $parmstr; - - $parmstr = str_replace('&', '&', $parmstr); // clean when it comes from the DB - $parm = explode('|', str_replace(array('\|', '\&', '\&'), array('%%__pipe__%%', '%%__ampamp__%%', '%%__amp__%%'), $parmstr), 2); - - $multi = str_replace('%%__pipe__%%', '|', $parm[0]); - if ($first2array) - { - parse_str($multi, $multi); - foreach ($multi as $k => $v) - { - $multi[str_replace(array('%%__ampamp__%%', '%%__amp__%%'), array('&', '&'), $k)] = str_replace(array('%%__ampamp__%%', '%%__amp__%%'), array('&', '&'), $v); - } - } - - if (varset($parm[1])) - { - // second paramater as a string - allow to be further passed to shortcodes - $parmstr = str_replace(array('%%__pipe__%%', '%%__ampamp__%%', '%%__amp__%%'), array('\|', '\&', '\&'), $parm[1]); - parse_str(str_replace('%%__pipe__%%', '|', $parm[1]), $params); - foreach ($params as $k => $v) - { - $params[str_replace(array('%%__ampamp__%%', '%%__amp__%%'), array('&', '&'), $k)] = str_replace(array('%%__ampamp__%%', '%%__amp__%%'), array('&', '&'), $v); - } - } - else - { - $parmstr = ''; - $params = array(); - } - - return array(1 => $multi, 2 => $params, 3 => $parmstr); - } - - - /** - * Remove Social Media Trackers from a $_GET array based on key matches. - * @param array $get - * @return array - */ - public static function removeTrackers($get = array()) - { - $trackers = array('fbclid','utm_source','utm_medium','utm_content','utm_campaign','elan'); - - foreach($trackers as $val) - { - if(isset($get[$val])) - { - unset($get[$val]); - } - } - - return $get; - - } - - -} +_request = (e_HTTP === '/') ? ltrim(e_REQUEST_URI,'/') : str_replace(e_HTTP,'', e_REQUEST_URI) ; + + $this->_config = e107::getUrlConfig(); + $this->_alias = e107::getPref('e_url_alias'); + + $this->_rootnamespace = e107::getPref('url_main_module'); + $this->_legacy = e107::getPref('url_config'); + $this->_legacyAliases = e107::getPref('url_aliases'); + + + $this->setRootNamespace(); + + } + + /** + * Detect older e_url system. + * @return bool + */ + private function isLegacy() + { + + $arr = (!empty($this->_legacyAliases[e_LAN])) ? array_merge($this->_legacy,$this->_legacyAliases[e_LAN]) : $this->_legacy; + + $list = array_keys($arr); + + foreach($list as $leg) + { + if(strpos($this->_request,$leg.'/') === 0 || $this->_request === $leg) + { + return true; + } + + } + + return false; + } + + + /** + * @return string + */ + public function getInclude() + { + return $this->_include; + } + + + + private function setRootNamespace() + { + + $plugs = array_keys($this->_config); + + if(!empty($this->_rootnamespace) && in_array($this->_rootnamespace,$plugs)) // Move rootnamespace check to the end of the list. + { + $v = $this->_config[$this->_rootnamespace]; + unset($this->_config[$this->_rootnamespace]); + $this->_config[$this->_rootnamespace] = $v; + } + + } + + + public function run() + { + $pref = e107::getPref(); + $tp = e107::getParser(); + + if(empty($this->_config) || empty($this->_request) || $this->_request === 'index.php' || $this->isLegacy() === true) + { + return false; + } + + $replaceAlias = array('{alias}\/?','{alias}/?','{alias}\/','{alias}/',); + + foreach($this->_config as $plug=>$cfg) + { + if(empty($pref['e_url_list'][$plug])) // disabled. + { + e107::getDebug()->log('e_URL for '.$plug.' is disabled.'); + continue; + } + + foreach($cfg as $k=>$v) + { + + if(empty($v['regex'])) + { + // e107::getMessage()->addDebug("Skipping empty regex: ".$k.""); + continue; + } + + + if(!empty($v['alias'])) + { + $alias = (!empty($this->_alias[e_LAN][$plug][$k])) ? $this->_alias[e_LAN][$plug][$k] : $v['alias']; + // e107::getMessage()->addDebug("e_url alias found: ".$alias.""); + if(!empty($this->_rootnamespace) && $this->_rootnamespace === $plug) + { + $v['regex'] = str_replace($replaceAlias, '', $v['regex']); + } + else + { + + $v['regex'] = str_replace('{alias}', $alias, $v['regex']); + } + } + + + $regex = '#'.$v['regex'].'#'; + + if(empty($v['redirect'])) + { + continue; + } + + + $newLocation = preg_replace($regex, $v['redirect'], $this->_request); + + if($newLocation != $this->_request) + { + $redirect = e107::getParser()->replaceConstants($newLocation); + list($file,$query) = explode("?", $redirect,2); + + $get = array(); + if(!empty($query)) + { + // issue #3171 fix double ampersand in case of wrong query definition + $query = str_replace('&&', '&', $query); + parse_str($query,$get); + } + + + foreach($get as $gk=>$gv) + { + $_GET[$gk] = $gv; + } + + e107::getDebug()->log('e_URL in '.$plug.' with key: '.$k.' matched '.$v['regex'].' and included: '.$file.' with $_GET: '.print_a($_GET,true),1); + + if(file_exists($file)) + { + define('e_CURRENT_PLUGIN', $plug); + define('e_QUERY', str_replace('&&', '&', $query)); // do not add to e107_class.php + define('e_URL_LEGACY', $redirect); + + $this->_include= $file; + return true; + // exit; + } + elseif(getperms('0')) + { + + echo "
"; + echo "

SEF Debug Info

"; + echo "File missing: ".$file; + echo "
Matched key: ".$k.""; + print_a($v); + echo "
"; + + } + + } + } + + } + + + + + } + + + /** + * Singleton implementation + * @return e_url + */ + public static function instance() + { + if(null == self::$_instance) + { + self::$_instance = new self(); + } + return self::$_instance; + } + + + +} + + + + + +/** + * e107 Front controller + */ +class eFront +{ + /** + * Singleton instance + * @var eFront + */ + private static $_instance; + + /** + * @var eDispatcher + */ + protected $_dispatcher; + + /** + * @var eRequest + */ + protected $_request; + + /** + * @var eRouter + */ + protected $_router; + + + protected $_response; + + /** + * @var string path to file to include - the old deprecated way of delivering content + */ + protected static $_legacy = ''; + + /** + * Constructor + */ + private function __construct() + { + } + + /** + * Cloning not allowed + * + */ + private function __clone() + { + } + + /** + * Singleton implementation + * @return eFront + */ + public static function instance() + { + if(null == self::$_instance) + { + self::$_instance = new self(); + } + return self::$_instance; + } + + /** + * Dispatch + */ + public function dispatch(eRequest $request = null, eResponse $response = null, eDispatcher $dispatcher = null) + { + if(null === $request) + { + if(null === $this->getRequest()) + { + $request = new eRequest(); + $this->setRequest($request); + } + else $request = $this->getRequest(); + } + elseif(null === $this->getRequest()) $this->setRequest($request); + + if(null === $response) + { + if(null === $this->getResponse()) + { + $response = new eResponse(); + $this->setResponse($response); + } + else $response = $this->getResponse(); + } + elseif(null === $this->getRequest()) $this->setRequest($request); + + + if(null === $dispatcher) + { + if(null === $this->getDispatcher()) + { + $dispatcher = new eDispatcher(); + $this->setDispatcher($dispatcher); + } + else $dispatcher = $this->getDispatcher(); + } + elseif(null === $this->getDispatcher()) $this->setDispatcher($dispatcher); + + + // set dispatched status true, required for checkLegacy() + $request->setDispatched(true); + + $router = $this->getRouter(); + + // If current request not already routed outside the dispatch method, route it + if(!$request->routed) $router->route($request); + + $c = 0; + // dispatch loop + do + { + $c++; + if($c > 100) + { + throw new eException("Too much dispatch loops", 1); + } + + // dispatched status true on first loop + $router->checkLegacy($request); + + // dispatched by default - don't allow legacy to alter dispatch status + $request->setDispatched(true); + + // legacy mod - return control to the bootstrap + if(self::isLegacy()) + { + return; + } + + // for the good players - dispatch loop - no more BC! + try + { + $dispatcher->dispatch($request, $response); + } + catch(eException $e) + { + echo $request->getRoute().' - '.$e->getMessage(); + exit; + } + + + } while (!$request->isDispatched()); + } + + /** + * Init all objects required for request dispatching + * @return eFront + */ + public function init() + { + $request = new eRequest(); + $this->setRequest($request); + + $dispatcher = new eDispatcher(); + $this->setDispatcher($dispatcher); + + $router = new eRouter(); + $this->setRouter($router); + + /** @var eResponse $response */ + $response = e107::getSingleton('eResponse'); + $this->setResponse($response); + + return $this; + } + + /** + * Dispatch + * @param string|eRequest $route + */ + public function run($route = null) + { + if($route) + { + if(is_object($route) && ($route instanceof eRequest)) $this->setRequest($route); + elseif(null !== $route && null !== $this->getRequest()) $this->getRequest()->setRoute($route); + } + try + { + $this->dispatch(); + } + catch(eException $e) + { + echo $e->getMessage(); + exit; + } + + } + + /** + * Application instance (e107 class) + * @return e107 + */ + public static function app() + { + return e107::getInstance(); + } + + /** + * Get dispatcher instance + * @return eDispatcher + */ + public function getDispatcher() + { + return $this->_dispatcher; + } + + /** + * Set dispatcher + * @param eDispatcher $dispatcher + * @return eFront + */ + public function setDispatcher(eDispatcher $dispatcher) + { + $this->_dispatcher = $dispatcher; + return $this; + } + + /** + * Get request instance + * @return eRequest + */ + public function getRequest() + { + return $this->_request; + } + + /** + * Set request + * @param eRequest $request + * @return eFront + */ + public function setRequest(eRequest $request) + { + $this->_request = $request; + return $this; + } + + /** + * Get response instance + * @return eResponse + */ + public function getResponse() + { + return $this->_response; + } + + /** + * Set response + * @param eResponse $response + * @return eFront + */ + public function setResponse(eResponse $response) + { + $this->_response = $response; + return $this; + } + + /** + * Get router instance + * @return eRouter + */ + public function getRouter() + { + return $this->_router; + } + + /** + * Set router instance + * @return eFront + */ + public function setRouter(eRouter $router) + { + $this->_router = $router; + return $this; + } + + /** + * Set/get legacy status of the current request + * @param boolean $status + * @return boolean + */ + public static function isLegacy($status = null) + { + if(null !== $status) + { + if(!empty($status[0]) && ($status[0] === '{')) + { + $status = e107::getParser()->replaceConstants($status); + } + self::$_legacy = $status; + } + return self::$_legacy; + } +} + +/** + * e107 Dispatcher + * It decides how to dispatch the request. + */ +class eDispatcher +{ + protected static $_configObjects = array(); + + public function dispatch(eRequest $request = null, eResponse $response = null) + { + $controllerName = $request->getControllerName(); + $moduleName = $request->getModuleName(); + $className = $this->isDispatchable($request, false); + + // dispatch based on rule settings + if(!$className) + { + if($controllerName == 'index') // v2.x upgrade has not been run yet. + { + e107::getRedirect()->redirect(e_ADMIN."admin.php"); + } + + throw new eException("Invalid controller '".$controllerName."'"); + } + + $controller = new $className($request, $response); + if(!($controller instanceof eController)) + { + throw new eException("Controller $controller is not an instance of eController"); + } + + $actionName = $request->getActionMethodName(); + + ob_start(); + + $controller->dispatch($actionName); + + $content = ob_get_contents(); + ob_end_clean(); + + $response->appendBody($content); + unset($controller); + } + + /** + * Get path to the e_url handler + * @param string $module + * @param string $location plugin|core|override + * @param boolean $sc + * @return string path + */ + public static function getConfigPath($module, $location, $sc = false) + { + $tmp = explode('/', $location); + $custom = ''; + $location = $tmp[0]; + if(isset($tmp[1]) && !empty($tmp[1])) + { + $custom = $tmp[1].'_'; + } + unset($tmp); + if($module !== '*') $module .= '/'; + + switch ($location) + { + case 'plugin': + //if($custom) $custom = 'url/'.$custom; + if(!defined('e_CURRENT_PLUGIN')) + { + define('e_CURRENT_PLUGIN', rtrim($module,'/')); // TODO Move to a better location. + } + return $sc ? '{e_PLUGIN}'.$module.'url/'.$custom.'url.php' : e_PLUGIN.$module.'url/'.$custom.'url.php'; + break; + + case 'core': + if($module === '*') return $sc ? '{e_CORE}url/' : e_CORE.'url/'; + return $sc ? '{e_CORE}url/'.$module.$custom.'url.php' : e_CORE.'url/'.$module.$custom.'url.php'; + break; + + case 'override': + if($module === '*') return $sc ? '{e_CORE}override/url/' : e_CORE.'override/url/' ; + return $sc ? '{e_CORE}override/url/'.$module.$custom.'url.php' : e_CORE.'override/url/'.$module.$custom.'url.php' ; + break; + + default: + return null; + break; + } + } + + /** + * Get path to url configuration subfolders + * @param string $module + * @param string $location plugin|core|override + * @param boolean $sc + * @return string path + */ + public static function getConfigLocationPath($module, $location, $sc = false) + { + switch ($location) + { + case 'plugin': + return $sc ? '{e_PLUGIN}'.$module.'/url/' : e_PLUGIN.$module.'/url/'; + break; + + case 'core': + return $sc ? '{e_CORE}url/'.$module.'/' : e_CORE.'url/'.$module.'/'; + break; + + case 'override': + return $sc ? '{e_CORE}override/url/'.$module.'/' : e_CORE.'override/url/'.$module.'/'; + break; + + default: + return null; + break; + } + } + + /** + * Get dispatch system path + * @param string $location plugin|core|override + * @param string $plugin required only when $location is plugin + * @param boolean $sc + * @return string path + */ + public static function getDispatchLocationPath($location, $plugin = null, $sc = false) + { + switch ($location) + { + case 'plugin': + if(!$plugin) return null; + return $sc ? '{e_PLUGIN}'.$plugin.'/controllers/' : e_PLUGIN.$plugin.'/controllers/'; + break; + + case 'core': + return $sc ? '{e_CORE}controllers/' : e_CORE.'controllers/'; + break; + + case 'override': + return $sc ? '{e_CORE}override/controllers/' : e_CORE.'override/controllers/'; + break; + + default: + return null; + break; + } + } + + /** + * Get full dispatch system path + * @param string $module + * @param string $location plugin|core|override + * @param boolean $sc + * @return string path + */ + public static function getDispatchPath($module, $location, $sc = false) + { + switch ($location) + { + case 'plugin': + return $sc ? '{e_PLUGIN}'.$module.'/controllers/' : e_PLUGIN.$module.'/controllers/'; + break; + + case 'core': + return $sc ? '{e_CORE}controllers/'.$module.'/' : e_CORE.'controllers/'.$module.'/'; + break; + + case 'override': + return $sc ? '{e_CORE}override/controllers/'.$module.'/' : e_CORE.'override/controllers/'.$module.'/'; + break; + + default: + return null; + break; + } + } + + /** + * Get include path to a given module/controller + * + * @param string $module valid module name + * @param string $controller controller name + * @param string $location core|plugin|override + * @param boolean $sc return relative (false) OR shortcode (true) path + * @return string controller path + */ + public static function getControllerPath($module, $controller, $location = null, $sc = false) + { + if(null === $location) $location = self::getDispatchLocation($module); + + return ($location ? self::getDispatchPath($module, $location, $sc).$controller.'.php': null); + } + + /** + * Get class name of a given module/controller + * + * @param string $module valid module name + * @param string $controllerName controller name + * @param string $location core|plugin|override + * @return string controller path + */ + public static function getControllerClass($module, $controllerName, $location = null) + { + if(null === $location) $location = self::getDispatchLocation($module); + + return ($location ? $location.'_'.$module.'_'.$controllerName.'_controller' : null); + } + + + /** + * Get controller object + * + * @param eRequest $request + * @param boolean $checkOverride whether to check the override location + * @return eController null if not dispatchable + */ + public function getController(eRequest $request, $checkOverride = true) + { + $class_name = $this->isDispatchable($request, true, $checkOverride); + if(!$class_name) return null; + + return new $class_name(); + } + + /** + * Check if given module/controller is dispatchable + * @param string $module valid module name + * @param string $controllerName controller name + * @param string $location core|plugin|override + * @param boolean $checkOverride whether to check the override location + * @return string class name OR false if not dispatchable + */ + public function isDispatchableModule($module, $controllerName, $location, $checkOverride = false) + { + if($checkOverride || $location == 'override') + { + $path = self::getControllerPath($module, $controllerName, 'override', false); + + $class_name = self::getControllerClass($module, $controllerName, 'override'); + if($class_name && !class_exists($class_name, false) && is_readable($path)) include_once($path); + + if($class_name && class_exists($class_name, false)) return $class_name; + } + + // fallback to original dispatch location if any + if($location === 'override') + { + // check for real location + if(($location = eDispatcher::getModuleRealLocation($module)) === null) return false; + } + + if($location !== 'override') + { + $path = self::getControllerPath($module, $controllerName, $location, false); + + $class_name = self::getControllerClass($module, $controllerName, $location); + if(!$class_name) return false; + + if(!class_exists($class_name, false) && is_readable($path)) include_once($path); + + if(class_exists($class_name, false)) return $class_name; + } + return false; + } + + /** + * Automated version of self::isDispatchableModule() + * @param eRequest $request + * @param boolean $checkReflection deep check - proper subclassing, action + * @param boolean $checkOverride try override controller folder first + * @return mixed class name OR false if not dispatchable + */ + public function isDispatchable(eRequest $request, $checkReflection = false, $checkOverride = true) + { + $location = self::getDispatchLocation($request->getModuleName()); + + $controllerName = $request->getControllerName(); + $moduleName = $request->getModuleName(); + $className = false; + + // dispatch based on url_config preference value, if config location is override and there is no + // override controller, additional check against real controller location will be made + if($location) + { + $className = $this->isDispatchableModule($moduleName, $controllerName, $location, $checkOverride); + } + //else + //{ + # Disable plugin check for routes with no config info - prevent calling of non-installed plugins + # We may allow this for plugins which don't have plugin.xml in the future + // $className = $this->isDispatchableModule($moduleName, $controllerName, 'plugin', $checkOverride); + // if(!$className) + //$className = $this->isDispatchableModule($moduleName, $controllerName, 'core', $checkOverride); + //} + + if(empty($className)) return false; + elseif(!$checkReflection) return $className; + + $rfl = new ReflectionClass($className); + $method = $request->getActionMethodName(); + if($rfl->isSubclassOf('eController') && $rfl->hasMethod($method) && $rfl->getMethod($method)->isPublic() && !$rfl->getMethod($method)->isStatic()) + return $className; + + return false; + } + + /** + * Get class name of a given module config + * + * @param string $module valid module name + * @param string $location core|plugin|override[/custom] + * @return string controller path + */ + public static function getConfigClassName($module, $location) + { + $tmp = explode('/', $location); + $custom = ''; + $location = $tmp[0]; + if(isset($tmp[1]) && !empty($tmp[1])) + { + $custom = $tmp[1].'_'; + } + unset($tmp); + $module .= '_'; + + // we need to prepend location to avoid namespace colisions + return $location.'_'.$module.$custom.'url'; + } + + /** + * Get config object for a module + * + * @param string $module valid module name + * @param string $location core|plugin|override[/custom] + * @return eUrlConfig + */ + public static function getConfigObject($module, $location = null) + { + if(null === $location) + { + $location = self::getModuleConfigLocation($module); + if(!$location) return null; + } + $reg = $module.'/'.$location; + if(isset(self::$_configObjects[$reg])) return self::$_configObjects[$reg]; + $className = self::getConfigClassName($module, $location); + if(!class_exists($className, false)) + { + $path = self::getConfigPath($module, $location, false); + if(!is_readable($path)) return null; + include_once($path); + + if(!class_exists($className, false)) return null; + } + $obj = new $className(); + $obj->init(); + self::$_configObjects[$reg] = $obj; + $obj = null; + + return self::$_configObjects[$reg]; + } + + /** + * Auto discover module location from stored in core prefs data + * @param string $module + * @return mixed + */ + public static function getModuleConfigLocation($module) + { + //retrieve from config prefs + return e107::findPref('url_config/'.$module, ''); + } + + /** + * Auto discover module location from stored in core prefs data + * @param string $module + * @return mixed|null|string + */ + public static function getDispatchLocation($module) + { + //retrieve from prefs + $location = self::getModuleConfigLocation($module); + if(!$location) return null; + + if(($pos = strpos($location, '/'))) //can't be 0 + { + return substr($location, 0, $pos); + } + return $location; + } + + + /** + * Auto discover module real location (and not currently set from url adminsitration) from stored in core prefs data + * @param string $module + */ + public static function getModuleRealLocation($module) + { + //retrieve from prefs + $searchArray = e107::findPref('url_modules'); + if(!$searchArray) return null; + + $search = array('core', 'plugin', 'override'); + + foreach ($search as $location) + { + $_searchArray = vartrue($searchArray[$location], array()); + if(in_array($module, $_searchArray)) return $location; + } + return null; + } +} + +/** + * URL manager - parse and create URLs based on rules set + * Inspired by Yii Framework UrlManager + */ +class eRouter +{ + /** + * Configuration array containing all available syste routes and route object configuration values + * @var array + */ + protected $_rules = array(); + + /** + * List of all system wide available aliases + * This includes multi-lingual configurations as well + * @var array + */ + protected $_aliases = array(); + + /** + * Cache for rule objects + * @var array + */ + protected $_parsedRules = array(); // array of rule objects + + /** + * Global config values per rule set + * @var array + */ + protected $_globalConfig = array(); + + /** + * Module name which is used for site main namespace + * Example mysite.com/news/News Item => converted to mysite.com/News Item + * NOTE: Could be moved to rules config + * + * @var string + */ + protected $_mainNsModule = ''; + + /** + * Default URL suffix - to be added to end of all urls (e.g. '.html') + * This value can be overridden per rule item + * NOTE could be moved to rules config only + * @var string + */ + public $urlSuffix = ''; + + /** + * @var string GET variable name for route. Defaults to 'route'. + */ + public $routeVar = 'route'; + + /** + * @var string + */ + const FORMAT_GET = 'get'; + + /** + * @var string + */ + const FORMAT_PATH = 'path'; + + /** + * @var string + */ + private $_urlFormat = self::FORMAT_PATH; + + /** + * Not found route + * @var string + */ + public $notFoundRoute = 'system/error/notfound'; + + protected $_defaultAssembleOptions = array('full' => false, 'amp' => '&', 'equal' => '=', 'encode' => true); + + /** + * Not found URL - used when system route not found and 'url_error_redirect' core pref is true + * TODO - user friendly URL ('/system/404') when system config is ready ('/system/404') + * @var string + */ + public $notFoundUrl = 'system/error/404?type=routeError'; + + + + + public function __construct() + { + $this->_init(); + } + + /** + * Init object + * @return void + */ + protected function _init() + { + // Gather all rules, add-on info, cache, module for main namespace etc + $this->_loadConfig() + ->setAliases(); + // we need config first as setter does some checks if module can be set as main + $this->setMainModule(e107::getPref('url_main_module', '')); + } + + /** + * Set module for default namespace + * @param string $module + * @return eRouter + */ + public function setMainModule($module) + { + if(!$module || !$this->isModule($module) || !$this->getConfigValue($module, 'allowMain')) return $this; + $this->_mainNsModule = $module; + return $this; + } + + /** + * Get main url namespace module + * @return string + */ + public function getMainModule() + { + return $this->_mainNsModule; + } + + /** + * Check if given module is the main module + * @param string $module + * @return boolean + */ + public function isMainModule($module) + { + return ($this->_mainNsModule === $module); + } + + + /** + * @return string get|path + */ + public function getUrlFormat() + { + return $this->_urlFormat; + } + + + /** + * Load config and url rules, if not available - build it on the fly + * @return eRouter + */ + protected function _loadConfig() + { + if(!is_readable(e_CACHE_URL.'config.php')) $config = $this->buildGlobalConfig(); + else $config = include(e_CACHE_URL.'config.php'); + + if(!$config) $config = array(); + + $rules = array(); + + foreach ($config as $module => $c) + { + $rules[$module] = $c['rules']; + unset($config[$module]['rules']); + $config[$module] = $config[$module]['config']; + } + $this->_globalConfig = $config; + $this->setRuleSets($rules); + + return $this; + } + + public static function clearCache() + { + if(file_exists(e_CACHE_URL.'config.php')) + { + @unlink(e_CACHE_URL.'config.php'); + } + } + + /** + * Build unified config.php + */ + public function buildGlobalConfig($save = true) + { + $active = e107::getPref('url_config', array()); + + $config = array(); + foreach ($active as $module => $location) + { + $_config = array(); + $obj = eDispatcher::getConfigObject($module, $location); + $path = eDispatcher::getConfigPath($module, $location, true); + + if(null !== $obj) + { + $_config = $obj->config(); + $_config['config']['configPath'] = $path; + $_config['config']['configClass'] = eDispatcher::getConfigClassName($module, $location); + } + if(!isset($_config['config'])) $_config['config'] = array(); + + $_config['config']['location'] = $location; + if(!isset($_config['config']['format']) || !in_array($_config['config']['format'], array(self::FORMAT_GET, self::FORMAT_PATH))) + { + $_config['config']['format'] = $this->getUrlFormat(); + } + + if(!isset($_config['rules'])) $_config['rules'] = array(); + + foreach ($_config['rules'] as $pattern => $rule) + { + if(!is_array($rule)) + { + $_config['rules'][$pattern] = array($rule); + } + } + + $config[$module] = $_config; + } + + if($save) + { + $fileContent = 'mode = 'fname'; + $files = $file->setFileInfo('fname') + ->get_files($path, '^([a-z_]{1,}_)?url\.php$'); + + + foreach ($files as $file) + { + if(null === $location) + { + $c = eRouter::file2config($file, $location); + if($c) $ret[] = $c; + continue; + } + $ret[] = eRouter::file2config($file, $location); + } + return $ret; + } + + /** + * Convert filename to configuration string + * @param string $filename + * @param string $location core|plugin|override + */ + public static function file2config($filename, $location = '') + { + if($filename == 'url.php') return $location; + if($location) $location .= '/'; + return $location.substr($filename, 0, strrpos($filename, '_')); + } + + /** + * Detect all available system url modules, used as a map on administration configuration path + * and required (same structure) {@link from eDispatcher::adminBuildConfig()) + * This is a very liberal detection, as it doesn't require config file. + * It goes through both config and dispatch locations and registers directory tree as modules + * The only exception are plugins - if plugin requires install (plugin.xml) and it is not installed, + * it won't be registered + * Another important thing is - core has always higher priority, as plugins are not allowed to + * directly override core modules. At this moment, core modules could be overloaded only via override configs (e107_core/override/url/) + * and controllers (e107_core/override/controllers) + * This array is stored as url_modules core preference + * + * @param string $type possible values are all|plugin|core|override + * @return array available system url modules stored as url_modules core preference + */ + public static function adminReadModules($type = 'all') + { + $f = e107::getFile(); + $ret = array('core' => array(), 'plugin' => array(), 'override' => array()); + + if($type == 'all' || $type = 'core') + { + $location = eDispatcher::getDispatchLocationPath('core'); + // search for controllers first + $ret['core'] = $f->get_dirs($location); + + // merge with configs + $configArray = $f->get_dirs(eDispatcher::getConfigPath('*', 'core')); + foreach ($configArray as $config) + { + if(!in_array($config, $ret['core'])) + { + $ret['core'][] = $config; + } + } + sort($ret['core']); + } + + if($type == 'all' || $type = 'plugin') + { + $plugins = $f->get_dirs(e_PLUGIN); + foreach ($plugins as $plugin) + { + // DON'T ALLOW PLUGINS TO OVERRIDE CORE!!! + // This will be possible in the future under some other, more controllable form + if(in_array($plugin, $ret['core'])) continue; + + $location = eDispatcher::getDispatchLocationPath('plugin', $plugin); + $config = eDispatcher::getConfigPath($plugin, 'plugin'); + + if(e107::isInstalled($plugin)) + { + if(is_dir($location) || is_readable($config)) + { + $ret['plugin'][] = $plugin; + } + continue; + } + + // Register only those who don't need install and may be dispatchable + if((!is_readable(e_PLUGIN.$plugin.'/plugin.php') && !is_readable(e_PLUGIN.$plugin.'/plugin.xml'))) + { + if(is_dir($location) || is_readable($config)) + { + $ret['plugin'][] = $plugin; + } + } + } + sort($ret['plugin']); + } + + if($type == 'all' || $type = 'override') + { + // search for controllers first + $location = eDispatcher::getDispatchLocationPath('override'); + $ret['override'] = $f->get_dirs($location); + + // merge with configs + $configArray = $f->get_dirs(eDispatcher::getConfigPath('*', 'override')); + foreach ($configArray as $config) + { + if(!in_array($config, $ret['override'])) + { + $ret['override'][] = $config; + } + } + sort($ret['override']); + + // remove not installed plugin locations, possible only for 'all' type + if($type == 'all') + { + foreach ($ret['override'] as $i => $l) + { + // it's a plugin override, but not listed in current plugin array - remove + if(in_array($l, $plugins) && !in_array($l, $ret['plugin'])) + { + unset($ret['override'][$i]); + } + } + } + } + + return $ret; + } + + /** + * Rebuild configuration array, stored as url_config core preference + * More strict detection compared to {@link eDispatcher::adminReadModules()} + * Current flat array containing config locations per module are rebuilt so that new + * modules are registered, missing modules - removed. Additionally fallback to the default location + * is done if current user defined location is not readable + * @see eDispatcher::adminReadModules() + * @param array current configuration array (url_config core preference like) + * @param array available URL modules as detected by {@link eDispatcher::adminReadModules()} and stored as url_modules core preference value + * @return array new url_config array + */ + public static function adminBuildConfig($current, $adminReadModules = null) + { + if(null === $adminReadModules) $adminReadModules = self::adminReadModules(); + + $ret = array(); + $all = array_unique(array_merge($adminReadModules['core'], $adminReadModules['plugin'], $adminReadModules['override'])); + foreach ($all as $module) + { + if(isset($current[$module])) + { + // current contains custom (readable) config location e.g. news => core/rewrite + if(strpos($current[$module], '/') !== false && is_readable(eDispatcher::getConfigPath($module, $current[$module]))) + { + $ret[$module] = $current[$module]; + continue; + } + + // in all other cases additional re-check will be made - see below + } + + if(in_array($module, $adminReadModules['override'])) + { + // core check + if(in_array($module, $adminReadModules['core'])) + { + $mustHave = is_readable(eDispatcher::getConfigPath($module, 'core')); + $has = is_readable(eDispatcher::getConfigPath($module, 'override')); + + // No matter if it must have, it has e_url config + if($has) $ret[$module] = 'override'; + // It must have but it doesn't have e_url config, fallback + elseif($mustHave && !$has) $ret[$module] = 'core'; + // Rest is always core as controller override is done on run time + else $ret[$module] = 'core'; + } + // plugin check + elseif(in_array($module, $adminReadModules['plugin'])) + { + $mustHave = is_readable(eDispatcher::getConfigPath($module, 'plugin')); + $has = is_readable(eDispatcher::getConfigPath($module, 'override')); + + // No matter if it must have, it has e_url config + if($has) $ret[$module] = 'override'; + // It must have but it doesn't have e_url config, fallback + elseif($mustHave && !$has) $ret[$module] = 'plugin'; + // Rest is always plugin as config is most important, controller override check is done on run time + else $ret[$module] = 'plugin'; + } + // standalone override module + else + { + $ret[$module] = 'override'; + } + + } + // default core location + elseif(in_array($module, $adminReadModules['core'])) + { + $ret[$module] = 'core'; + } + // default plugin location + elseif(in_array($module, $adminReadModules['plugin'])) + { + $ret[$module] = 'plugin'; + } + } + return $ret; + } + + /** + * Detect available config locations (readable check), based on available url_modules {@link eDispatcher::adminReadModules()} core preference arrays + * Used to rebuild url_locations core preference value + * @see eDispatcher::adminBuildConfig() + * @see eDispatcher::adminReadModules() + * @param array $available {@link eDispatcher::adminReadModules()} stored as url_modules core preference + * @return array available config locations, stored as url_locations core preference + */ + public static function adminBuildLocations($available = null) + { + $ret = array(); + if(null === $available) $available = self::adminReadModules(); + + $fl = e107::getFile(); + + // Core + foreach ($available['core'] as $module) + { + // Default module + $ret[$module] = array('core'); + + // read sub-locations + $path = eDispatcher::getConfigLocationPath($module, 'core'); + //$sub = $fl->get_dirs($path); + $sub = eRouter::adminReadConfigs($path); + + if($sub) + { + foreach ($sub as $moduleSub) + { + // auto-override: override available (controller or url config), check for config + if(in_array($module, $available['override']) && is_readable(eDispatcher::getConfigPath($module, 'override/'.$moduleSub))) + { + $ret[$module][] = 'override/'.$moduleSub; + } + // no override available, register the core location + elseif(is_readable(eDispatcher::getConfigPath($module, 'core/'.$moduleSub))) + { + $ret[$module][] = 'core/'.$moduleSub; + } + } + } + } + + + // Plugins + foreach ($available['plugin'] as $module) + { + // Default module + $ret[$module] = array('plugin'); + + // read sub-locations + $path = eDispatcher::getConfigLocationPath($module, 'plugin'); + //$sub = $fl->get_dirs($path); + $sub = eRouter::adminReadConfigs($path); + + if($sub) + { + foreach ($sub as $moduleSub) + { + // auto-override: override available (controller or url config), check for config + if(in_array($module, $available['override']) && is_readable(eDispatcher::getConfigPath($module, 'override/'.$moduleSub))) + { + $ret[$module][] = 'override/'.$moduleSub; + } + // no override available, register the core location + elseif(is_readable(eDispatcher::getConfigPath($module, 'plugin/'.$moduleSub))) + { + $ret[$module][] = 'plugin/'.$moduleSub; + } + } + } + } + + // Go through all overrides, register those who don't belong to core & plugins as standalone core modules + foreach ($available['override'] as $module) + { + // either it is a core/plugin module or e_url.php is not readable - continue + if(in_array($module, $available['core']) || in_array($module, $available['plugin'])) + { + continue; + } + + // Default module + $ret[$module] = array('override'); + + // read sub-locations + $path = eDispatcher::getConfigLocationPath($module, 'override'); + //$sub = $fl->get_dirs($path); + $sub = eRouter::adminReadConfigs($path); + + if($sub) + { + foreach ($sub as $moduleSub) + { + if(is_readable(eDispatcher::getConfigPath($module, 'override/'.$moduleSub))) + { + $ret[$module][] = 'override/'.$moduleSub; + } + } + } + } + + return $ret; + } + + /** + * Match current aliases against currently available module and languages + * @param array $currentAliases url_aliases core preference + * @param array $currentConfig url_config core preference + * @return array cleaned aliases + */ + public static function adminSyncAliases($currentAliases, $currentConfig) + { + if(empty($currentAliases)) return array(); + + $modules = array_keys($currentConfig); + + // remove non existing languages + $lng = e107::getLanguage(); + $lanList = $lng->installed(); + + if(is_array($currentAliases)) + { + foreach ($currentAliases as $lanCode => $aliases) + { + $lanName = $lng->convert($lanCode); + if(!$lanName || !in_array($lanName, $lanList)) + { + unset($currentAliases[$lanCode]); + continue; + } + + // remove non-existing modules + foreach ($aliases as $alias => $module) + { + if(!isset($currentConfig[$module])) unset($currentAliases[$lanCode][$alias]); + } + } + } + return $currentAliases; + } + + /** + * Retrieve global configuration array for a single or all modules + * @param string $module system module + * @return array configuration + */ + public function getConfig($module = null) + { + if(null === $module) return $this->_globalConfig; + + return isset($this->_globalConfig[$module]) ? $this->_globalConfig[$module] : array(); + } + + /** + * Retrieve single value from a module global configuration array + * @param string $module system module + * @return array configuration + */ + public function getConfigValue($module, $key, $default = null) + { + return isset($this->_globalConfig[$module]) && isset($this->_globalConfig[$module][$key]) ? $this->_globalConfig[$module][$key] : $default; + } + + /** + * Get system name of a module by its alias + * Returns null if $alias is not an existing alias + * @param string $alias + * @param string $lan optional language alias check. Example $lan = 'bg' (search for Bulgarian aliases) + * @return string module + */ + public function getModuleFromAlias($alias, $lan = null) + { + if($lan) return e107::findPref('url_aliases/'.$lan.'/'.$alias, null); + return (isset($this->_aliases[$alias]) ? $this->_aliases[$alias] : null); + } + + /** + * Get alias name for a module + * Returns null if module doesn't have an alias + * @param string $module + * @param string $lan optional language alias check. Example $lan = 'bg' (search for Bulgarian aliases) + * @return string alias + */ + public function getAliasFromModule($module, $lan = null) + { + if($lan) + { + $aliases = e107::findPref('url_aliases/'.$lan, array()); + return (in_array($module, $aliases) ? array_search($module, $aliases) : null); + } + return (in_array($module, $this->_aliases) ? array_search($module, $this->_aliases) : null); + } + + /** + * Check if alias exists + * @param string $alias + * @param string $lan optional language alias. Example $lan = 'bg' (search for Bulgarian aliases) + * @return boolean + */ + public function isAlias($alias, $lan = null) + { + if($lan) + { + $aliases = e107::findPref('url_aliases/'.$lan, array()); + return isset($aliases[$alias]); + } + return isset($this->_aliases[$alias]); + } + + /** + * Check if there is an alias for provided module + * @param string $module + * @param string $lan optional language alias check. Example $lan = 'bg' (search for Bulgarian aliases) + * @return boolean + */ + public function hasAlias($module, $lan = null) + { + if($lan) + { + $aliases = e107::findPref('url_aliases/'.$lan, array()); + return in_array($module, $aliases); + } + return in_array($module, $this->_aliases); + } + + /** + * Get all available module aliases + * @param string $lan optional language alias check. Example $lan = 'bg' (search for Bulgarian aliases) + * @return array + */ + public function getAliases($lanCode = null) + { + if($lanCode) + { + return e107::findPref('url_aliases/'.$lanCode, array()); + } + return $this->_aliases; + } + + /** + * Set module aliases + * @param array $aliases + * @return eRouter + */ + public function setAliases($aliases = null) + { + if(null === $aliases) + { + $lanCode = e107::getLanguage()->convert(e_LANGUAGE); + + $aliases = e107::findPref('url_aliases/'.$lanCode, array()); + } + $this->_aliases = $aliases; + + return $this; + } + + /** + * Check if provided module is present in the rules config + * @param string module + * @return boolean + */ + public function isModule($module) + { + return isset($this->_globalConfig[$module]); + } + + /** + * Check if the passed value is valid module or module alias, returns system module + * or null on failure + * @param string $module + * @param boolean $strict check for existence if true + * @return string module + */ + public function retrieveModule($module, $strict = true) + { + if($this->isAlias($module)) + $module = $this->getModuleFromAlias($module); + + if($strict && (!$module || !$this->isModule($module))) + return null; + + return $module; + } + + /** + * Set rule config for this instance + * @param array $rules + * @return void + */ + public function setRuleSets($rules) + { + $this->_rules = $rules; + } + + /** + * Retrieve rule set for a module + * @param string $module + */ + public function getRuleSet($module) + { + return (isset($this->_rules[$module]) ? $this->_rules[$module] : array()); + } + + /** + * Get all rule sets + */ + public function getRuleSets() + { + return $this->_rules; + } + + /** + * Retrive array of eUrlRule objects for given module + */ + public function getRules($module) + { + return $this->_processRules($module); + } + + /** + * Process rule set array, create rule objects + * TODO - rule cache + * @param string $module + * @return array processed rule set + */ + protected function _processRules($module) + { + if(!$this->isModule($module)) return array(); + + if(!isset($this->_parsedRules[$module])) + { + $rules = $this->getRuleSet($module); + $config = $this->getConfig($module); + $this->_parsedRules[$module] = array(); + $map = array('urlSuffix' => 'urlSuffix', 'legacy' => 'legacy', 'legacyQuery' => 'legacyQuery', 'mapVars' => 'mapVars', 'allowVars' => 'allowVars', 'matchValue' => 'matchValue'); + foreach ($rules as $pattern => $set) + { + foreach ($map as $key => $value) + { + if(!isset($set[$value]) && isset($config[$key])) + { + $set[$value] = $config[$key]; + } + } + $this->_parsedRules[$module][$pattern] = $this->createRule($set, $pattern); + } + } + return $this->_parsedRules[$module]; + } + + /** + * Create rule object + * + * @param string $route + * @param string|array $pattern + * @param boolean $cache + * @return eUrlRule + */ + protected function createRule($route, $pattern = null, $cache = false) + { + return new eUrlRule($route, $pattern, $cache); + } + + + private function _debug($label,$val=null, $line=null) + { + if(!deftrue('e_DEBUG_SEF')) + { + return false; + } + + e107::getDebug()->log("

SEF: ".$label . " ".basename(__FILE__)." (".$line.")

".print_a($val,true)); + } + + /** + * Route current request + * @param eRequest $request + * @return boolean + */ + public function route(eRequest $request, $checkOnly = false) + { + $request->routed = false; + + if(isset($_GET[$this->routeVar])) + { + $rawPathInfo = $_GET[$this->routeVar]; + unset($_GET[$this->routeVar]); + $this->_urlFormat = self::FORMAT_GET; + } + else + { + $rawPathInfo = rawurldecode($request->getPathInfo()); + //$this->_urlFormat = self::FORMAT_PATH; + } + + + + // Ignore social trackers when determining route. + $get = eHelper::removeTrackers($_GET); + + // Route to front page - index/index/index route + if(!$rawPathInfo && (!$this->getMainModule() || empty($get))) + { + // front page settings will be detected and front page will be rendered + $request->setRoute('index/index/index'); + $request->addRouteHistory($rawPathInfo); + $request->routed = true; + return true; + } + + // max number of parts is actually 4 - module/controller/action/[additional/pathinfo/vars], here for reference only + $parts = $rawPathInfo ? explode('/', $rawPathInfo, 4) : array(); + + $this->_debug('parts',$parts, __LINE__); + + // find module - check aliases + $module = $this->retrieveModule($parts[0]); + $mainSwitch = false; + + // no module found, switch to Main module (pref) if available + if(null === $module && $this->getMainModule() && $this->isModule($this->getMainModule())) + { + $module = $this->getMainModule(); + $rawPathInfo = $module.'/'.$rawPathInfo; + array_unshift($parts, $module); + $mainSwitch = true; + } + + $request->routePathInfo = $rawPathInfo; + + $this->_debug('module',$module, __LINE__); + $this->_debug('rawPathInfo',$rawPathInfo, __LINE__); + + + // valid module + if(null !== $module) + { + // we have valid module + $config = $this->getConfig($module); + + $this->_debug('config',$module, __LINE__); + + // set legacy state + eFront::isLegacy(varset($config['legacy'])); + + // Don't allow single entry if required by module config + if(vartrue($config['noSingleEntry'])) + { + $request->routed = true; + if(!eFront::isLegacy()) + { + $request->setRoute($this->notFoundRoute); + return false; + } + // legacy entry point - include it later in the bootstrap, legacy query string will be set to current + $request->addRouteHistory($rawPathInfo); + return true; + } + + // URL format - the one set by current config overrides the auto-detection + $format = isset($config['format']) && $config['format'] ? $config['format'] : $this->getUrlFormat(); + + //remove leading module, unnecessary overhead while matching + array_shift($parts); + $rawPathInfo = $parts ? implode('/', $parts) : ''; + $pathInfo = $this->removeUrlSuffix($rawPathInfo, $this->urlSuffix); + + // retrieve rules if any and if needed + $rules = $format == self::FORMAT_PATH ? $this->getRules($module) : array(); + + // Further parsing may still be needed + if(empty($rawPathInfo)) + { + $rawPathInfo = $pathInfo; + } + + // parse callback + if(vartrue($config['selfParse'])) + { + // controller/action[/additional/parms] + if(vartrue($config['urlSuffix'])) $rawPathInfo = $this->removeUrlSuffix($rawPathInfo, $config['urlSuffix']); + $route = $this->configCallback($module, 'parse', array($rawPathInfo, $_GET, $request, $this, $config), $config['location']); + } + // default module route + elseif($format == self::FORMAT_GET || !$rules) + { + $route = $pathInfo; + } + // rules available - try to match an Url Rule + elseif($rules) + { + // $this->_debug('rules',$rules, __LINE__); + + foreach ($rules as $rule) + { + $route = $rule->parseUrl($this, $request, $pathInfo, $rawPathInfo); + + + + if($route !== false) + { + eFront::isLegacy($rule->legacy); // legacy include override + + $this->_debug('rule->legacy',$rule->legacy, __LINE__); + $this->_debug('rule->parseCallback',$rule->parseCallback, __LINE__); + + if($rule->parseCallback) + { + $this->configCallback($module, $rule->parseCallback, array($request), $config['location']); + } + + // parse legacy query string if any + $this->_debug('rule->legacyQuery',$rule->legacyQuery, __LINE__); + + if(null !== $rule->legacyQuery) + { + $obj = eDispatcher::getConfigObject($module, $config['location']); + // eUrlConfig::legacyQueryString set as legacy string by default in eUrlConfig::legacy() method + $vars = new e_vars($request->getRequestParams()); + $vars->module = $module; + $vars->controller = $request->getController(); + $vars->action = $request->getAction(); + if($rule->allowVars) + { + foreach ($rule->allowVars as $key) + { + if(isset($_GET[$key]) && !$request->isRequestParam($key)) + { + // sanitize + $vars->$key = preg_replace('/[^\d\w\-]/', '', $_GET[$key]); + } + } + } + $obj->legacyQueryString = e107::getParser()->simpleParse($rule->legacyQuery, $vars, '0'); + + $this->_debug('obj->legacyQueryString',$obj->legacyQueryString, __LINE__); + unset($vars, $obj); + } + break; + } + } + } + + // append module to be registered in the request object + if(false !== $route) + { + // don't modify if true - request directly modified by config callback + if(!$request->routed) + { + if(eFront::isLegacy()) $this->configCallback($module, 'legacy', array($route, $request), $config['location']); + $route = $module.'/'.$route; + } + } + // No route found, we didn't switched to main module auto-magically + elseif(!$mainSwitch && vartrue($config['errorRoute'])) + { + $route = !$checkOnly ? $module.'/'.$config['errorRoute'] : false; + } + + } + + // final fallback + if(!vartrue($route)) + { + if($request->routed) + { + $route = $request->getRoute(); + } + + if(!$route) + { + $route = $this->notFoundRoute; + eFront::isLegacy(''); // reset legacy - not found route isn't legacy call + $request->routed = true; + if($checkOnly) return false; + ## Global redirect on error option + if(e107::getPref('url_error_redirect', false) && $this->notFoundUrl) + { + $redirect = $this->assemble($this->notFoundUrl, '', 'encode=0&full=1'); + //echo $redirect; exit; + e107::getRedirect()->redirect($redirect, true, 404); + } + } + } + + $this->_debug('route',$route, __LINE__); + + $request->setRoute($route); + $request->addRouteHistory($route); + $request->routed = true; + return true; + } + + /** + * And more BC + * Checks and does some addtional logic if registered module is of type legacy + * @param eRequest $request + * @return void + */ + public function checkLegacy(eRequest $request) + { + $module = $request->getModule(); + + // forward from controller to a legacy module - bad stuff + if(!$request->isDispatched() && $this->getConfigValue($module, 'legacy')) + { + eFront::isLegacy($this->getConfigValue($module, 'legacy')); + + $url = $this->assemble($request->getRoute(), $request->getRequestParams()); + $request->setRequestInfo($url)->setPathInfo(null)->setRoute(null); + + $_GET = $request->getRequestParams(); + $_SERVER['QUERY_STRING'] = http_build_query($request->getRequestParams(), null, '&'); + + // Infinite loop impossible, as dispatcher will break because of the registered legacy path + $this->route($request); + } + } + + /** + * Convenient way to call config methods + */ + public function configCallback($module, $callBack, $params, $location) + { + if(null == $location) $location = eDispatcher::getModuleConfigLocation($module); + if(!$module || !($obj = eDispatcher::getConfigObject($module, $location))) return false; + + return call_user_func_array(array($obj, $callBack), $params); + } + + /** + * Convert assembled url to shortcode + * + * @param string $route + * @param array $params + * @param array $options {@see eRouter::$_defaultAssembleOptions} + */ + public function assembleSc($route, $params = array(), $options = array()) + { + //if(is_string($options)) parse_str($options, $options); + $url = $this->assemble($route, $params, $options); + return e107::getParser()->createConstants($url, 'mix'); + } + + /** + * Assemble system URL + * Examples: + * assemble('/'); // index page URL e.g. / or /site_folder/ + * $router->assemble('news/view/item?id=1'); // depends on current news config, possible return value is /news/1 + * $router->assemble('*', 'id=1'); // use current request info - /module/controller/action?id=1 + * $router->assemble('* /* /newaction'); // (NO EMPTY SPACES) change only current action - /module/controller/newaction + * $newsItem = array('news_id' => 1, 'news_sef' => 'My Title', ...); // as retrieved from DB + * $router->assemble('news/view/item', $newsItem); // All unused key=>values will be removed and NOT appended as GET vars + * + * @param string $route + * @param array $params + * @param array $options {@see eRouter::$_defaultAssembleOptions} + */ + public function assemble($route, $params = array(), $options = array()) + { + // TODO - url options + $request = eFront::instance()->getRequest(); + if(is_string($options)) parse_str($options, $options); + $options = array_merge($this->_defaultAssembleOptions, $options); + $base = ($options['full'] ? SITEURLBASE : '').$request->getBasePath(); + + $anc = ''; + + + if(is_string($params)) parse_str($params, $params); + if(isset($params['#'])) + { + $anc = '#'.$params['#']; + unset($params['#']); + } + + // Config independent - Deny parameter keys, useful for directly denying sensitive data e.g. password db fields + if(isset($options['deny'])) + { + $list = array_map('trim', explode(',', $options['deny'])); + foreach ($list as $value) + { + unset($params[$value]); + } + unset($list); + } + + // Config independent - allow parameter keys, useful to directly allow data (and not to rely on config allowVars) e.g. when retrieved from db + if(isset($options['allow'])) + { + $list = array_map('trim', explode(',', $options['allow'])); + $_params = $params; + $params = array(); + foreach ($list as $value) + { + if(isset($_params[$value])) $params[$value] = $_params[$value]; + } + unset($list, $_params); + } + + # Optional convenient masks for creating system URL's + if($route === '/' || empty($route)) + { + if($params) + { + $params = $this->createPathInfo($params, $options); + return $base.'?'.$params; + } + return $base; + } + elseif(strpos($route, '?') !== false) + { + $tmp = explode('?', $route, 2); + $route = $tmp[0]; + parse_str($tmp[1], $params); + unset($tmp); + } + + if($route === '*') + { + $route = $route = explode('/', $request->getRoute()); + } + elseif(strpos($route, '*') !== false) + { + $route = explode('/', $route, 3); + if($route[0] === '*') $route[0] = $request->getModule(); + if(isset($route[1]) && $route[1] === '*') $route[1] = $request->getController(); + } + else + { + $route = explode('/', $route, 3); + } + + // we don't know anything about this route, just build it blind + if(!$this->isModule($route[0])) + { + if($params) + { + $params = $this->createPathInfo($params, $options); + return $base.implode('/', $route).'?'.$params; + } + return $base.implode('/', $route); + } + + # fill in index when needed - XXX not needed, may be removed soon + switch (count($route)) + { + case 1: + $route[1] = 'index'; + $route[2] = 'index'; + break; + case 2: + $route[2] = 'index'; + break; + } + + # aliases + $module = $route[0]; + $config = $this->getConfig($module); + + $alias = $this->hasAlias($module, vartrue($options['lan'], null)) ? $this->getAliasFromModule($module, vartrue($options['lan'], null)) : $module; + $route[0] = $alias; + if($options['encode']) $alias = rawurlencode($alias); + + $format = isset($config['format']) && $config['format'] ? $config['format'] : self::FORMAT_GET; + + $urlSuffix = ''; + + // Fix base url for legacy links + if(vartrue($config['noSingleEntry'])) $base = $options['full'] ? SITEURL : e_HTTP; + elseif(self::FORMAT_GET !== $config['format']) + { + $urlSuffix = $this->urlSuffix; + if(isset($config['urlSuffix'])) $urlSuffix = $config['urlSuffix']; + } + + // Create by config callback + if(vartrue($config['selfCreate'])) + { + $tmp = $this->configCallback($module, 'create', array(array($route[1], $route[2]), $params, $options), $config['location']); + + if(empty($tmp)) return '#not-found'; + + if(is_array($tmp)) + { + $route = $tmp[0]; + $params = $tmp[1]; + + if($options['encode']) $route = array_map('rawurlencode', $route); + $route = implode('/', $route); + + if(!$route) + { + $urlSuffix = ''; + if(!$this->isMainModule($module)) $route = $alias; + } + elseif (!$this->isMainModule($module)) + { + $route = $alias.'/'.$route; + } + + } + else + { + // relative url returned + return $base.$tmp.$anc; + } + unset($tmp); + + if($format === self::FORMAT_GET) + { + $params[$this->routeVar] = $route; + $route = ''; + } + + if($params) + { + $params = $this->createPathInfo($params, $options); + return $base.$route.$urlSuffix.'?'.$params.$anc; + } + + return $base.$route.$urlSuffix.$anc; + } + + + // System URL create routine + $rules = $this->getRules($module); + if($format !== self::FORMAT_GET && !empty($rules)) + { + foreach ($rules as $k => $rule) + { + if (($url = $rule->createUrl($this, array($route[1], $route[2]), $params, $options)) !== false) + { + return $base.rtrim(($this->isMainModule($module) ? '' : $alias.'/').$url, '/').$anc; + } + } + } + + // default - module/controller/action + if($this->isMainModule($module)) unset($route[0]); + if($route[2] == 'index') + { + unset($route[2]); + if($route[1] == 'index') unset($route[1]); + } + + # Modify params if required + if($params) + { + if(varset($config['mapVars'])) + { + foreach ($config['mapVars'] as $srcKey => $dstKey) + { + if (isset($params[$srcKey])) + { + $params[$dstKey] = $params[$srcKey]; + unset($params[$srcKey]); + } + } + } + + // false means - no vars are allowed, nothing to preserve here + if(varset($config['allowVars']) === false) $params = array(); + // default empty array value - try to guess what's allowed - mapVars is the best possible candidate + elseif(empty($config['allowVars']) && !empty($config['mapVars'])) $params = array_unique(array_values($config['mapVars'])); + // disallow everything but valid URL parameters + if(!empty($config['allowVars'])) + { + $copy = $params; + $params = array(); + foreach ($config['allowVars'] as $key) + { + if(isset($copy[$key])) $params[$key] = $copy[$key]; + } + unset($copy); + } + + if($format === self::FORMAT_GET) + { + $urlSuffix = ''; + $copy = $params; + $params = array(); + $params[$this->routeVar] = implode('/', $route); + foreach ($copy as $key => $value) + { + $params[$key] = $value; + } + unset($copy); + $route = array(); + } + $params = $this->createPathInfo($params, $options); + $route = implode('/', $route); + if(!$route || $route == $alias) $urlSuffix = ''; + return $base.$route.$urlSuffix.'?'.$params.$anc; + } + $route = implode('/', $route); + if(!$route || $route == $alias) $urlSuffix = ''; + + + return $format === self::FORMAT_GET ? $base.'?'.$this->routeVar.'='.$route.$anc : $base.$route.$urlSuffix.$anc; + } + + /** + * Alias of assemble() + */ + public function url($route, $params = array()) + { + return $this->assemble($route, $params); + } + + /** + * Creates a path info based on the given parameters. + * XXX - maybe we can switch to http_build_query(), should be able to do everything we need in a much better way + * + * @param array $params list of GET parameters + * @param array $options rawurlencode, equal, encode and amp settings + * @param string $key this is used internally for recursive calls + * + * @return string the created path info + */ + public function createPathInfo($params, $options, $key = null) + { + $pairs = array(); + $equal = $options['equal']; + $encode = $options['encode']; + $ampersand = !$encode && $options['amp'] == '&' ? '&' : $options['amp']; + foreach ($params as $k => $v) + { + if (null !== $key) $k = $key.'['.rawurlencode($k).']'; + + if (is_array($v)) $pairs[] = $this->createPathInfo($v, $options, $k); + else + { + if(null === $v) + { + if($encode) + { + $k = null !== $key ? $k : rawurlencode($k); + } + $pairs[] = $k; + continue; + } + if($encode) + { + $k = null !== $key ? $k : rawurlencode($k); + $v = rawurlencode($v); + } + $pairs[] = $k.$equal.$v; + } + } + return implode($ampersand, $pairs); + } + + /** + * Parses a path info into URL segments + * Be sure to not use non-unique chars for equal and ampersand signs, or you'll break your URLs + * + * @param eRequest $request + * @param string $pathInfo path info + * @param string $equal + * @param string $ampersand + */ + public function parsePathInfo($pathInfo, $equal = '/', $ampersand = '/') + { + if ('' === $pathInfo) return; + + if ($equal != $ampersand) $pathInfo = str_replace($equal, $ampersand, $pathInfo); + $segs = explode($ampersand, $pathInfo.$ampersand); + + $segs = explode('/', $pathInfo); + $ret = array(); + + for ($i = 0, $n = count($segs); $i < $n - 1; $i += 2) + { + $key = $segs[$i]; + if ('' === $key) continue; + $value = $segs[$i + 1]; + // array support + if (($pos = strpos($key, '[')) !== false && ($pos2 = strpos($key, ']', $pos + 1)) !== false) + { + $name = substr($key, 0, $pos); + // numerical array + if ($pos2 === $pos + 1) + $ret[$name][] = $value; + // associative array + else + { + $key = substr($key, $pos + 1, $pos2 - $pos - 1); + $ret[$name][$key] = $value; + } + } + else + { + $ret[$key] = $value; + + } + } + return $ret; + } + + /** + * Removes the URL suffix from path info. + * @param string $pathInfo path info part in the URL + * @param string $urlSuffix the URL suffix to be removed + * + * @return string path info with URL suffix removed. + */ + public function removeUrlSuffix($pathInfo, $urlSuffix) + { + if ('' !== $urlSuffix && substr($pathInfo, -strlen($urlSuffix)) === $urlSuffix) return substr($pathInfo, 0, -strlen($urlSuffix)); + else return $pathInfo; + } +} + +class eException extends Exception +{ + +} + +/** + * Based on Yii Framework UrlRule handler + */ +class eUrlRule +{ + /** + * + * For example, ".html" can be used so that the URL looks like pointing to a static HTML page. + * Defaults to null, meaning using the value of {@link cl_shop_core_url::urlSuffix}. + * + * @var string the URL suffix used for this rule. + */ + public $urlSuffix; + + /** + * When this rule is used to parse the incoming request, the values declared in this property + * will be injected into $_GET. + * + * @var array the default GET parameters (name=>value) that this rule provides. + */ + public $defaultParams = array(); + + /** + * @var string module/controller/action + */ + public $route; + + /** + * @var array the mapping from route param name to token name (e.g. _r1=><1>) + */ + public $references = array(); + + /** + * @var string the pattern used to match route + */ + public $routePattern; + + /** + * @var string regular expression used to parse a URL + */ + public $pattern; + + /** + * @var string template used to construct a URL + */ + public $template; + + /** + * @var array list of parameters (name=>regular expression) + */ + public $params = array(); + + /** + * @var boolean whether the URL allows additional parameters at the end of the path info. + */ + public $append; + + /** + * @var array list of SourceKey=>DestinationKey associations + */ + public $mapVars = array(); + + /** + * Numerical array of allowed parameter keys. If set, everything else will be wiped out from the passed parameter array + * @var array + */ + public $allowVars = array(); + + /** + * Should be values matched vs route patterns when assembling URLs + * Warning SLOW when true!!! + * @var mixed true or 1 for preg_match (extremely slower), or 'empty' for only empty check (better) + */ + public $matchValue; + + /** + * Method member of module config object, to be called after successful request parsing + * @var string + */ + public $parseCallback; + + /** + * Shortcode path to the old entry point e.g. '{e_BASE}news.php' + * @var string + */ + public $legacy; + + /** + * Template used for automated recognition of legacy QueryString (parsed via simpleParser with values of retrieved requestParameters) + * @var string + */ + public $legacyQuery; + + /** + * Core regex templates + * Example usage - route will result in + * @var array + */ + public $regexTemplates = array( + 'az' => '[A-Za-z]+', // NOTE - it won't match non-latin word characters! + 'alphanum' => '[\w\pL]+', + 'sefsecure' => '[\w\pL\s\-+.,]+', + 'secure' => '[^\/\'"\\<%]+', + 'number' => '[\d]+', + 'username' => '[\w\pL.\-\s!,]+', // TODO - should equal to username pattern, sync it + 'azOptional' => '[A-Za-z]{0,}', + 'alphanumOptional' => '[\w\pL]{0,}', + 'sefsecureOptional' => '[\w\pL\s\-+.,]{0,}', + 'secureOptional' => '[^\/\'"\\<%]{0,}', + 'numberOptional' => '[\d]{0,}', + 'usernameOptional' => '[\w\pL.\-\s!,]{0,}', // TODO - should equal to username pattern, sync it + ); + + /** + * User defined regex templates + * @var array + */ + public $varTemplates = array(); + + /** + * All regex templates + * @var e_var + */ + protected $_regexTemplates; + + + /** + * Constructor. + * @param string $route the route of the URL (controller/action) + * @param string $pattern the pattern for matching the URL + */ + public function __construct($route, $pattern, $fromCache = false) + { + if (is_array($route)) + { + if ($fromCache && !$pattern) + { + $this->setData($route); + $this->_regexTemplates = new e_vars($this->regexTemplates); + return; + } + + $this->setData($route); + if($this->defaultParams && is_string($this->defaultParams)) + { + parse_str($this->defaultParams, $this->defaultParams); + } + $route = $this->route = $route[0]; + } + else $this->route = $route; + + $tr2['/'] = $tr['/'] = '\\/'; + + if (strpos($route, '<') !== false && preg_match_all('/<(\w+)>/', $route, $matches2)) + { + foreach ($matches2[1] as $name) $this->references[$name] = "<$name>"; + } + + if($this->varTemplates) + { + // don't override core regex templates + $this->regexTemplates = array_merge($this->varTemplates, $this->regexTemplates); + $this->varTemplates = array(); + } + $this->_regexTemplates = new e_vars($this->regexTemplates); + + if (preg_match_all('/<(\w+):?(.*?)?>/', $pattern, $matches)) + { + $tokens = array_combine($matches[1], $matches[2]); + $tp = e107::getParser(); + foreach ($tokens as $name => $value) + { + if ($value === '') $value = '[^\/]+'; + elseif($value[0] == '{') + { + $value = $tp->simpleParse($value, $this->_regexTemplates, '[^\/]+'); + } + $tr["<$name>"] = "(?P<$name>$value)"; + if (isset($this->references[$name])) $tr2["<$name>"] = $tr["<$name>"]; + else $this->params[$name] = $value; + } + } + + $p = rtrim($pattern, '*'); + $this->append = $p !== $pattern; + $p = trim($p, '/'); + $this->template = preg_replace('/<(\w+):?.*?>/', '<$1>', $p); + $this->pattern = '/^'.strtr($this->template, $tr).'\/?'; + if ($this->append) $this->pattern .= '/u'; + else $this->pattern .= '$/u'; + + if ($this->references !== array()) $this->routePattern = '/^'.strtr($this->route, $tr2).'$/u'; + } + + public function getData() + { + $vars = array_keys(get_class_vars(__CLASS__)); + $data = array(); + foreach ($vars as $prop) + { + $data[$prop] = $this->$prop; + } + return $data; + } + + protected function setData($data) + { + if (!is_array($data)) return; + $vars = array_keys(get_class_vars(__CLASS__)); + + foreach ($vars as $prop) + { + if (!isset($data[$prop])) continue; + $this->$prop = $data[$prop]; + } + } + + /** + * Creates a URL based on this rule. + * TODO - more clear logic and flexibility by building the query string + * + * @param eRouter $manager the router/manager + * @param string $route the route + * @param array $params list of parameters + * @param array $options + * @return mixed the constructed URL or false on error + */ + public function createUrl($manager, $route, $params, $options) + { + $case = 'i'; + $ampersand = $options['amp']; + $encode = vartrue($options['encode']); + + if(is_array($route)) $route = implode('/', $route); + + + + $tr = array(); + if ($route !== $this->route) + { + if ($this->routePattern !== null && preg_match($this->routePattern.$case, $route, $matches)) + { + foreach ($this->references as $key => $name) $tr[$name] = $matches[$key]; + } + else return false; + } + + // map vars first + foreach ($this->mapVars as $srcKey => $dstKey) + { + if (isset($params[$srcKey])/* && !isset($params[$dstKey])*/) + { + $params[$dstKey] = $params[$srcKey]; + unset($params[$srcKey]); + } + } + + // false means - no vars are allowed, preserve only route vars + if($this->allowVars === false) $this->allowVars = array_keys($this->params); + // empty array (default) - everything is allowed + + // disallow everything but valid URL parameters + if(!empty($this->allowVars)) + { + $copy = $params; + $params = array(); + $this->allowVars = array_unique(array_merge($this->allowVars, array_keys($this->params))); + foreach ($this->allowVars as $key) + { + if(isset($copy[$key])) $params[$key] = $copy[$key]; + } + unset($copy); + } + + foreach ($this->defaultParams as $key => $value) + { + if (isset($params[$key])) + { + if ($params[$key] == $value) unset($params[$key]); + else return false; + } + } + + foreach ($this->params as $key => $value) if (!isset($params[$key])) return false; + + if($this->matchValue) + { + + if('empty' !== $this->matchValue) + { + foreach($this->params as $key=>$value) + { + if(!preg_match('/'.$value.'/'.$case,$params[$key])) + return false; + } + } + else + { + foreach($this->params as $key=>$value) + { + if(empty($params[$key]) ) + return false; + } + } + } + + $tp = e107::getParser(); + $urlFormat = e107::getConfig()->get('url_sef_translate'); + + foreach ($this->params as $key => $value) + { + // FIX - non-latin URLs proper encoded + $tr["<$key>"] = rawurlencode($params[$key]); //todo transliterate non-latin + // $tr["<$key>"] = eHelper::title2sef($tp->toASCII($params[$key]), $urlFormat); // enabled to test. + unset($params[$key]); + } + + $suffix = $this->urlSuffix === null ? $manager->urlSuffix : $this->urlSuffix; + + // XXX TODO Find better place for this check which will affect all types of SEF URL configurations. (@see news/sef_noid_url.php for duplicate) + + + + + if($urlFormat == 'dashl' || $urlFormat == 'underscorel' || $urlFormat == 'plusl') // convert template to lowercase when using lowercase SEF URL format. + { + $this->template = strtolower($this->template); + } + + $url = strtr($this->template, $tr); + + // Work-around fix for lowercase username + if($urlFormat == 'dashl' && $this->route == 'profile/view') + { + $url = str_replace('%20','-', strtolower($url)); + } + + if(empty($params)) + { + return $url !== '' ? $url.$suffix : $url; + } + + // apppend not supported, maybe in the future...? + if ($this->append) $url .= '/'.$manager->createPathInfo($params, '/', '/').$suffix; + else + { + if ($url !== '') $url = $url.$suffix; + + $options['equal'] = '='; + $url .= '?'.$manager->createPathInfo($params, $options); + } + + + return rtrim($url, '/'); + } + + /** + * Parases a URL based on this rule. + * @param eRouter $manager the router/URL manager + * @param eRequest $request the request object + * @param string $pathInfo path info part of the URL + * @param string $rawPathInfo path info that contains the potential URL suffix + * @return mixed the route that consists of the controller ID and action ID or false on error + */ + public function parseUrl($manager, $request, $pathInfo, $rawPathInfo) + { + $case = 'i'; # 'i' = insensitive + + if ($this->urlSuffix !== null) $pathInfo = $manager->removeUrlSuffix($rawPathInfo, $this->urlSuffix); + + $pathInfo = rtrim($pathInfo, '/').'/'; + // pathInfo is decoded, pattern could be encoded - required for proper url assemble (e.g. cyrillic chars) + if (preg_match(rawurldecode($this->pattern).$case, $pathInfo, $matches)) + { + foreach ($this->defaultParams as $name => $value) + { + //if (!isset($_GET[$name])) $_REQUEST[$name] = $_GET[$name] = $value; + if (!$request->isRequestParam($name)) $request->setRequestParam($name, $value); + } + $tr = array(); + foreach ($matches as $key => $value) + { + if (isset($this->references[$key])) $tr[$this->references[$key]] = $value; + elseif (isset($this->params[$key])) + { + //$_REQUEST[$key] = $_GET[$key] = $value; + $request->setRequestParam($key, $value); + } + } + + if ($pathInfo !== $matches[0]) # Additional GET params exist + { + $manager->parsePathInfo($request, ltrim(substr($pathInfo, strlen($matches[0])), '/')); + } + return (null !== $this->routePattern ? strtr($this->route, $tr) : $this->route); + } + else return false; + } + +} + +abstract class eUrlConfig +{ + /** + * Registered by parse method legacy query string + */ + public $legacyQueryString = null; + + /** + * User defined initialization + */ + public function init() {} + + /** + * Retrieve module config options (including url rules if any) + * Return array is called once and cached, so runtime changes are not an option + * @return array + */ + abstract public function config(); + + /** + * Create URL callback, called only when config option selfParse is set to true + * Expected return array format: + * + * array( + * array(part1, part2, part3), + * array(parm1 => val1, parm2 => val2), + * ); + * + * @param array $route parts + * @param array $params + * @return array|string numerical of type (routeParts, GET Params)| string route or false on error + */ + public function create($route, $params = array(), $options = array()) {} + + /** + * Parse URL callback, called only when config option selfCreate is set to true + * TODO - register variable eURLConfig::currentConfig while initializing the object, remove from method arguments + * @param string $pathInfo + * @param array $params request parameters + * @param eRequest $request + * @param eRouter $router + * @param array $config + * @return string route or false on error + */ + public function parse($pathInfo, $params = array(), eRequest $request = null, eRouter $router = null, $config = array()) + { + return false; + } + + /** + * Legacy callback, used called when config option legacy is not empty + * By default it sets legacy query string to $legacyQueryString value (normaly assigned inside of the parse method) + * @param string $resolvedRoute + * @param eRequest $request + * @param string $callType 'route' - called once, when parsing the request, 'dispatch' - called inside the dispatch loop (in case of controller _forward) + * @param void + */ + public function legacy($resolvedRoute, eRequest $request, $callType = 'route') + { + if($this->legacyQueryString !== null) + { + $request->setLegacyQstring($this->legacyQueryString); + $request->setLegacyPage(); + } + } + + /** + * Developed mainly for legacy modules. + * It should be manually triggered inside of old entry point. The idea is + * to avoid multiple URL addresses having same content (bad SEO practice) + * FIXME - under construction + */ + public function forward() {} + + /** + * Admin interface callback, returns array with all required from administration data + * Return array structure: + * + * array( + * 'name' => 'Module name', + * 'label' => 'Profile Label', + * 'description' => 'Additional profile info, exmples etc.', + * ), + * 'form' => array(), // awaiting future development + * 'callbacks' => array(), // awaiting future development + * ); + * + */ + public function admin() { return array(); } + + /** + * Admin submit hook + * FIXME - under construction + */ + public function submit() {} + + /** + * Admin interface help messages, labels and titles + * FIXME - under construction + */ + public function help() {} + + +} + +/** + * Controller base class, actions are extending it + * + */ +class eController +{ + protected $_request; + protected $_response; + + public function __construct(eRequest $request, eResponse $response = null) + { + $this->setRequest($request) + ->setResponse($response) + ->init(); + } + + /** + * Custom init, always called in the constructor, no matter what is the request dispatch status + */ + public function init() {} + + /** + * Custom shutdown, always called after the controller dispatch, no matter what is the request dispatch status + */ + public function shutdown() {} + + /** + * Pre-action callback, fired only if dispatch status is still true and action method is found + */ + public function preAction() {} + + /** + * Post-action callback, fired only if dispatch status is still true and action method is found + */ + public function postAction() {} + + /** + * @param eRequest $request + * @return eController + */ + public function setRequest($request) + { + $this->_request = $request; + return $this; + } + + /** + * @return eRequest + */ + public function getRequest() + { + return $this->_request; + } + + /** + * @param eResponse $response + * @return eController + */ + public function setResponse($response) + { + $this->_response = $response; + return $this; + } + + /** + * @return eResponse + */ + public function getResponse() + { + return $this->_response; + } + + public function addBody($content) + { + $this->getResponse()->appendBody($content); + return $this; + } + + public function addMetaDescription($description) + { + $this->getResponse()->addMetaDescription($description); + return $this; + } + + /** + * Add document title + * @param string $title + * @param boolean $meta auto-add it as meta-title + * @return eResponse + */ + public function addTitle($title, $meta = true) + { + $this->getResponse()->appendTitle($title); + if($meta) $this->addMetaTitle(strip_tags($title)); + return $this; + } + + + public function addMetaTitle($title) + { + $this->getResponse()->addMetaTitle($title); + return $this; + } + + public function dispatch($actionMethodName) + { + $request = $this->getRequest(); + $content = ''; + + // init() could modify the dispatch status + if($request->isDispatched()) + { + if(method_exists($this, $actionMethodName)) + { + $this->preAction(); + // TODO request userParams() to store private data - check for noPopulate param here + if($request->isDispatched()) + { + $request->populateRequestParams(); + + // allow return output + $content = $this->$actionMethodName(); + if(!empty($content)) $this->addBody($content); + + if($request->isDispatched()) + { + $this->postAction(); + } + } + } + else + { + //TODO not found method by controller or default one + $action = substr($actionMethodName, 6); + throw new eException('Action "'.$action.'" does not exist'); + } + } + $this->shutdown(); + } + + public function run(eRequest $request = null, eResponse $response = null) + { + if(null === $request) $request = $this->getRequest(); + else $this->setRequest($request); + + if(null === $response) $response = $this->getResponse(); + else $this->setResponse($response); + + $action = $request->getActionMethodName(); + + $request->setDispatched(true); + $this->dispatch($action); + + return $this->getResponse(); + } + + protected function _redirect($url, $createURL = false, $code = null) + { + $redirect = e107::getRedirect(); + if($createURL) + { + $url = eFront::instance()->getRouter()->assemble($url, '', 'encode=0'); + } + if(strpos($url, 'http://') !== 0 && strpos($url, 'https://') !== 0) + { + $url = $url[0] == '/' ? SITEURLBASE.$url : SITEURL.$url; + } + $redirect->redirect($url, true, $code); + } + + /** + * System forward + * @param string $route + * @param array $params + */ + protected function _forward($route, $params = array()) + { + $request = $this->getRequest(); + + if(is_string($params)) + { + parse_str($params, $params); + } + + $oldRoute = $request->getRoute(); + $route = explode('/', trim($route, '/')); + + switch (count($route)) { + case 3: + if($route[0] !== '*') $request->setModule($route[0]); + if($route[1] !== '*') $request->setController($route[1]); + $request->setAction($route[2]); + break; + + case 2: + if($route[1] !== '*') $request->setController($route[0]); + $request->setAction($route[1]); + break; + + case 1: + $request->setAction($route[0]); + break; + + default: + return; + break; + } + + $request->addRouteHistory($oldRoute); + + if(false !== $params) $request->setRequestParams($params); + $request->setDispatched(false); + } + + /** + * @param string $methodName + * @param array $args + * @return void + * @throws eException + */ + public function __call($methodName, $args) + { + if ('action' == substr($methodName, 0, 6)) + { + $action = substr($methodName, 6); + throw new eException('Action "'.$action.'" does not exist', 2404); + } + + throw new eException('Method "'.$methodName.'" does not exist', 3404); + } +} + +/** + * @package e107 + * @subpackage e107_handlers + * @version $Id$ + * + * Base front-end controller + */ + +class eControllerFront extends eController +{ + /** + * Plugin name - used to check if plugin is installed + * Set this only if plugin requires installation + * @var string + */ + protected $plugin = null; + + /** + * Default controller access + * @var integer + */ + protected $userclass = e_UC_PUBLIC; + + /** + * Generic 404 page URL (redirect), SITEURL will be added + * @var string + */ + protected $e404 = '404.html'; + + /** + * Generic 403 page URL (redirect), SITEURL will be added + * @var string + */ + protected $e403 = '403.html'; + + /** + * Generic 404 route URL (forward) + * @var string + */ + protected $e404route = 'index/not-found'; + + /** + * Generic 403 route URL (forward) + * @var string + */ + protected $e403route = 'index/access-denied'; + + /** + * View renderer objects + * @var array + */ + protected $_validator; + + /** + * Per action access + * Format 'action' => userclass + * @var array + */ + protected $access = array(); + + /** + * User input filter (_GET) + * Format 'action' => array(var => validationArray) + * @var array + */ + protected $filter = array(); + + /** + * Base constructor - set 404/403 locations + */ + public function __construct(eRequest $request, eResponse $response = null) + { + parent::__construct($request, $response); + $this->_init(); + } + + /** + * Base init, called after the public init() - handle access restrictions + * The base init() method is able to change controller variables on the fly (e.g. access, filters, etc) + */ + final protected function _init() + { + // plugin check + if(null !== $this->plugin) + { + if(!e107::isInstalled($this->plugin)) + { + $this->forward403(); + return; + } + } + + // global controller restriction + if(!e107::getUser()->checkClass($this->userclass, false)) + { + $this->forward403(); + return; + } + + // by action access + if(!$this->checkActionPermissions()) exit; + + // _GET input validation + $this->validateInput(); + + // Set Render mode to module-controller-action, override possible within the action + $this->getResponse()->setRenderMod(str_replace('/', '-', $this->getRequest()->getRoute())); + } + + /** + * Check persmission for current action + * @return boolean + */ + protected function checkActionPermissions() + { + // per action restrictions + $action = $this->getRequest()->getAction(); + if(isset($this->access[$action]) && !e107::getUser()->checkClass($this->access[$action], false)) + { + $this->forward403(); + return false; + } + return true; + } + + public function redirect404() + { + e107::getRedirect()->redirect(SITEURL.$this->e404); + } + + public function redirect403() + { + e107::getRedirect()->redirect(SITEURL.$this->e403); + } + + public function forward404() + { + $this->_forward($this->e404route); + } + + public function forward403() + { + $this->_forward($this->e403route); + } + + /** + * Controller validator object + * @return e_validator + */ + public function getValidator() + { + if(null === $this->_validator) + { + $this->_validator = new e_validator('controller'); + } + + return $this->_validator; + } + + /** + * Register request parameters based on current $filter data (_GET only) + * Additional security layer + */ + public function validateInput() + { + $validator = $this->getValidator(); + $request = $this->getRequest(); + if(empty($this->filter) || !isset($this->filter[$request->getAction()])) return; + $validator->setRules($this->filter[$request->getAction()]) + ->validate($_GET); + + $validData = $validator->getValidData(); + + foreach ($validData as $key => $value) + { + if(!$request->isRequestParam($key)) $request->setRequestParam($key, $value); + } + $validator->clearValidateMessages(); + } + + /** + * System error message proxy + * @param string $message + * @param boolean $session + */ + public function messageError($message, $session = false) + { + return e107::getMessage()->addError($message, 'default', $session); + } + + /** + * System success message proxy + * @param string $message + * @param boolean $session + */ + public function messageSuccess($message, $session = false) + { + return e107::getMessage()->addSuccess($message, 'default', $session); + } + + /** + * System warning message proxy + * @param string $message + * @param boolean $session + */ + public function messageWarning($message, $session = false) + { + return e107::getMessage()->addWarning($message, 'default', $session); + } + + /** + * System debug message proxy + * @param string $message + * @param boolean $session + */ + public function messageDebug($message, $session = false) + { + return e107::getMessage()->addDebug($message, 'default', $session); + } +} + + +/** + * Request handler + * + */ +class eRequest +{ + /** + * @var string + */ + protected $_module; + + /** + * @var string + */ + protected $_controller; + + /** + * @var string + */ + protected $_action; + + /** + * Request status + * @var boolean + */ + protected $_dispatched = false; + + /** + * @var array + */ + protected $_requestParams = array(); + + /** + * @var string + */ + protected $_basePath; + + /** + * @var string + */ + protected $_pathInfo; + + + /** + * @var string + */ + protected $_requestInfo; + + /** + * Pathinfo string used for initial system routing + */ + public $routePathInfo; + + /** + * @var array + */ + protected $_routeHistory = array(); + + /** + * @var boolean if request is already routed - generally set by callbacks to notify router about route changes + */ + public $routed = false; + + /** + * Name of the bootstrap file + * @var string + */ + public $singleEntry = 'index.php'; + + /** + * Request constructor + */ + public function __construct($route = null) + { + if(null !== $route) + { + $this->setRoute($route); + $this->routed = true; + } + } + + /** + * Get system base path + * @return string + */ + public function getBasePath() + { + if(null == $this->_basePath) + { + $this->_basePath = e_HTTP; + if(!e107::getPref('url_disable_pathinfo')) $this->_basePath .= $this->singleEntry.'/'; + } + + return $this->_basePath; + } + + /** + * Set system base path + * @param string $basePath + * @return eRequest + */ + public function setBasePath($basePath) + { + $this->_basePath = $basePath; + return $this; + } + + /** + * Get path info + * If not set, it'll be auto-retrieved + * @return string path info + */ + public function getPathInfo() + { + if(null == $this->_pathInfo) + { + if($this->getBasePath() == $this->getRequestInfo()) + $this->_pathInfo = ''; // map to indexRoute + + else + $this->_pathInfo = substr($this->getRequestInfo(), strlen($this->getBasePath())); + + if($this->_pathInfo && trim($this->_pathInfo, '/') == trim($this->singleEntry, '/')) $this->_pathInfo = ''; + } + + return $this->_pathInfo; + } + + /** + * Override path info + * @param string $pathInfo + * @return eRequest + */ + public function setPathInfo($pathInfo) + { + $this->_pathInfo = $pathInfo; + return $this; + } + + /** + * @return string request info + */ + public function getRequestInfo() + { + if(null === $this->_requestInfo) + { + $this->_requestInfo = e_REQUEST_HTTP; + } + return $this->_requestInfo; + } + + + /** + * Override request info + * @param string $pathInfo + * @return eRequest + */ + public function setRequestInfo($requestInfo) + { + $this->_requestInfo = $requestInfo; + return $this; + } + + /** + * Quick front page check + */ + public static function isFrontPage($entryScript = 'index.php', $currentPathInfo = e_REQUEST_HTTP) + { + $basePath = e_HTTP; + if(!e107::getPref('url_disable_pathinfo')) $basePath .= $entryScript.'/'; + + return ($basePath == $currentPathInfo); + } + + /** + * Get current controller string + * @return string + */ + public function getController() + { + return $this->_controller; + } + + /** + * Get current controller name + * Example: requested controller-name or 'controller name' -> converted to controller_name + * @return string + */ + public function getControllerName() + { + return eHelper::underscore($this->_controller); + } + + /** + * Set current controller name + * Example: controller_name OR 'controller name' -> converted to controller-name + * Always sanitized + * @param string $controller + * @return eRequest + */ + public function setController($controller) + { + $this->_controller = strtolower(eHelper::dasherize($this->sanitize($controller))); + return $this; + } + + /** + * Get current module string + * @return string + */ + public function getModule() + { + return $this->_module; + } + + /** + * Get current module name + * Example: module-name OR 'module name' -> converted to module_name + * @return string + */ + public function getModuleName() + { + return eHelper::underscore($this->_module); + } + + /** + * Set current module name + * Example: module_name OR 'module name' -> converted to module-name + * Always sanitized + * @param string $module + * @return eRequest + */ + public function setModule($module) + { + $this->_module = strtolower(eHelper::dasherize($this->sanitize($module))); + return $this; + } + + /** + * Get current action string + * @return string + */ + public function getAction() + { + return $this->_action; + } + + /** + * Get current action name + * Example: action-name OR 'action name' OR action_name -> converted to ActionName + * @return string + */ + public function getActionName() + { + return eHelper::camelize($this->_action, true); + } + + /** + * Get current action method name + * Example: action-name OR 'action name' OR action_name -> converted to actionActionName + * @return string + */ + public function getActionMethodName() + { + return 'action'.eHelper::camelize($this->_action, true); + } + + /** + * Set current action name + * Example: action_name OR 'action name' OR Action_Name OR 'Action Name' -> converted to ation-name + * Always sanitized + * @param string $action + * @return eRequest + */ + public function setAction($action) + { + $this->_action = strtolower(eHelper::dasherize($this->sanitize($action))); + return $this; + } + + /** + * Get current route string/array -> module/controller/action + * @param boolean $array + * @return string|array route + */ + public function getRoute($array = false) + { + if(!$this->getModule()) + { + $route = array('index', 'index', 'index'); + } + else + { + $route = array( + $this->getModule(), + $this->getController() ? $this->getController() : 'index', + $this->getAction() ? $this->getAction() : 'index', + ); + } + return ($array ? $route : implode('/', $route)); + } + + /** + * Set current route + * @param string $route module/controller/action + * @return eRequest + */ + public function setRoute($route) + { + if(null === $route) + { + $this->_module = null; + $this->_controller = null; + $this->_action = null; + } + return $this->initFromRoute($route); + } + + /** + * System routing track, used in controllers forwarder + * @param string $route + * @return eRequest + */ + public function addRouteHistory($route) + { + $this->_routeHistory[] = $route; + return $this; + } + + /** + * Retrieve route from history track + * Based on $source we can retrieve + * - array of all history records + * - 'first' route record + * - 'last' route record + * - history record by its index number + * @param mixed $source + * @return string|array + */ + public function getRouteHistory($source = null) + { + if(null === $source) return $this->_routeHistory; + + if(!$this->_routeHistory) return null; + elseif('last' === $source) + { + return $this->_routeHistory[count($this->_routeHistory) -1]; + } + elseif('first' === $source) + { + return $this->_routeHistory[0]; + } + elseif(is_int($source)) + { + return isset($this->_routeHistory[$source]) ? $this->_routeHistory[$source] : null; + } + return null; + } + + /** + * Search route history for the given $route + * + * @param string $route + * @return integer route index or false if not found + */ + public function findRouteHistory($route) + { + return array_search($route, $this->_routeHistory); + } + + /** + * Populate module, controller and action from route string + * @param string $route + * @return array route data + */ + public function initFromRoute($route) + { + $route = trim($route, '/'); + if(!$route) + { + $route = 'index/index/index'; + } + $parts = explode('/', $route); + $this->setModule($parts[0]) + ->setController(vartrue($parts[1], 'index')) + ->setAction(vartrue($parts[2], 'index')); + + return $this;//->getRoute(true); + } + + /** + * Get request parameter + * @param string $key + * @param string $default value if key not set + * @return mixed value + */ + public function getRequestParam($key, $default = null) + { + return (isset($this->_requestParams[$key]) ? $this->_requestParams[$key] : $default); + } + + /** + * Check if request parameter exists + * @param string $key + * @return boolean + */ + public function isRequestParam($key) + { + return isset($this->_requestParams[$key]); + } + + /** + * Get request parameters array + * @return array value + */ + public function getRequestParams() + { + return $this->_requestParams; + } + + /** + * Set request parameter + * @param string $key + * @param mixed $value + * @return eRequest + */ + public function setRequestParam($key, $value) + { + $this->_requestParams[$key] = $value; + return $this; + } + + /** + * Set request parameters + * @param array $params + * @return eRequest + */ + public function setRequestParams($params) + { + $this->_requestParams = $params; + return $this; + } + + /** + * Populate current request parameters (_GET scope) + * @return eRequest + */ + public function populateRequestParams() + { + $rp = $this->getRequestParams(); + + foreach ($rp as $key => $value) + { + $_GET[$key] = $value; + } + return $this; + } + + /** + * More BC + * @param string $qstring + * @return eRequest + */ + public function setLegacyQstring($qstring = null) + { + if(defined('e_QUERY')) return $this; + + if(null === $qstring) + { + $qstring = self::getQueryString(); + } + + if(!defined('e_SELF')) + { + define("e_SELF", e_REQUEST_SELF); + } + + if(!defined('e_QUERY')) + { + define("e_QUERY", $qstring); + } + + $_SERVER['QUERY_STRING'] = e_QUERY; + + if(strpos(e_QUERY,"=")!==false ) // Fix for legacyQuery using $_GET ie. ?x=y&z=1 etc. + { + parse_str(str_replace(array('&'), array('&'), e_QUERY),$tmp); + foreach($tmp as $key=>$value) + { + $_GET[$key] = $value; + } + } + + return $this; + } + + /** + * And More BC :/ + * @param string $page + * @return eRequest + */ + public function setLegacyPage($page = null) + { + if(defined('e_PAGE')) return $this; + if(null === $page) + { + $page = eFront::isLegacy(); + } + if(!$page) + { + define('e_PAGE', $this->singleEntry); + } + else define('e_PAGE', basename(str_replace(array('{', '}'), '/', $page))); + return $this; + } + + /** + * And More from the same - BC :/ + * @return string + */ + public static function getQueryString() + { + $qstring = ''; + if($_SERVER['QUERY_STRING']) + { + $qstring = str_replace(array('{', '}', '%7B', '%7b', '%7D', '%7d'), '', rawurldecode($_SERVER['QUERY_STRING'])); + } + $qstring = str_replace('&', '&', e107::getParser()->post_toForm($qstring)); + return $qstring; + } + + /** + * Basic sanitize method for module, controller and action input values + * @param string $str string to be sanitized + * @param string $pattern optional replace pattern + * @param string $replace optional replace string, defaults to dash + */ + public function sanitize($str, $pattern='', $replace='-') + { + if (!$pattern) $pattern = '/[^\w\pL-]/u'; + + return preg_replace($pattern, $replace, $str); + } + + /** + * Set dispatched status of the request + * @param boolean $mod + * @return eRequest + */ + public function setDispatched($mod) + { + $this->_dispatched = $mod ? true : false; + return $this; + } + + /** + * Get dispatched status of the request + * @return boolean + */ + public function isDispatched() + { + return $this->_dispatched; + } +} + +class eResponse +{ + protected $_body = array('default' => ''); + protected $_title = array('default' => array()); + protected $_e_PAGETITLE = array(); + protected $_META_DESCRIPTION = array(); + protected $_META_KEYWORDS = array(); + protected $_render_mod = array('default' => 'default'); + protected $_meta_title_separator = ' - '; + protected $_meta_name_only = array('keywords', 'viewport'); // Keep FB happy. + protected $_meta_property_only = array('article:section', 'article:tag'); // Keep FB happy. + protected $_meta = array(); + protected $_title_separator = ' » '; + protected $_content_type = 'html'; + protected $_content_type_arr = array( + 'html' => 'text/html', + 'css' => 'text/css', + 'xml' => 'text/xml', + 'json' => 'application/json', + 'js' => 'application/javascript', + 'rss' => 'application/rss+xml', + 'soap' => 'application/soap+xml', + ); + + protected $_params = array( + 'render' => true, + 'meta' => false, + 'jsonNoTitle' => false, + 'jsonRender' => false, + ); + + public function setParam($key, $value) + { + $this->_params[$key] = $value; + return $this; + } + + public function setParams($params) + { + $this->_params = $params; + return $this; + } + + public function getParam($key, $default = null) + { + return (isset($this->_params[$key]) ? $this->_params[$key] : $default); + } + + public function isParam($key) + { + return isset($this->_params[$key]); + } + + public function addContentType($typeName, $mediaType) + { + $this->_content_type_arr[$typeName] = $mediaType; + return $this; + } + + public function getContentType() + { + return $this->_content_type; + } + + public function getContentMediaType($typeName) + { + if(isset($this->_content_type_arr[$typeName])) + return $this->_content_type_arr[$typeName]; + } + + public function setContentType($typeName) + { + $this->_content_type = $typeName; + } + + /** + * @return eResponse + */ + public function sendContentType() + { + $ctypeStr = $this->getContentMediaType($this->getContentType()); + if($ctypeStr) + { + header('Content-type: '.$this->getContentMediaType($this->getContentType()).'; charset=utf-8', TRUE); + } + return $this; + } + + /** + * @return eResponse + */ + public function addHeader($header, $override = false, $responseCode = null) + { + header($header, $override, $responseCode); + return $this; + } + + /** + * Append content + * @param str $body + * @param str $ns namespace + * @return eResponse + */ + public function appendBody($body, $ns = 'default') + { + if(!isset($this->_body[$ns])) + { + $this->_body[$ns] = ''; + } + $this->_body[$ns] .= $body; + + return $this; + } + + /** + * Set content + * @param str $body + * @param str $ns namespace + * @return eResponse + */ + public function setBody($body, $ns = 'default') + { + $this->_body[$ns] = $body; + return $this; + } + + + /** + * @param $name + * @param $content + * @return $this + */ + public function setMeta($name, $content) + { + foreach($this->_meta as $k=>$v) + { + if($v['name'] === $name) + { + $this->_meta[$k]['content'] = $content; + } + } + + return $this; + + } + + + /** + * Removes a Meta tag by name/property. + * + * @param string $name + * 'name' or 'property' for the meta tag we want to remove. + * + * @return eResponse $this + */ + public function removeMeta($name) + { + foreach($this->_meta as $k=>$v) + { + // Meta tags like: + if(isset($v['name']) && $v['name'] === $name) + { + unset($this->_meta[$k]); + continue; + } + + // Meta tags like: + if(isset($v['property']) && $v['property'] === $name) + { + unset($this->_meta[$k]); + } + } + + return $this; + } + + + /** + * Prepend content + * @param str $body + * @param str $ns namespace + * @return eResponse + */ + function prependBody($body, $ns = 'default') + { + if(!isset($this->_body[$ns])) + { + $this->_body[$ns] = ''; + } + $this->_body[$ns] = $content.$this->_body[$ns]; + + return $this; + } + + /** + * Get content + * @param string $ns + * @param boolean $reset + * @return string + */ + public function getBody($ns = 'default', $reset = false) + { + if(!isset($this->_body[$ns])) + { + $this->_body[$ns] = ''; + } + $ret = $this->_body[$ns]; + if($reset) unset($this->_body[$ns]); + + return $ret; + } + + /** + * @param string $title + * @param string $ns + * @return eResponse + */ + function setTitle($title, $ns = 'default') + { + + if(!is_string($ns) || empty($ns)) + { + $this->_title['default'] = array((string) $title); + } + else + { + $this->_title[$ns] = array((string) $title); + } + return $this; + } + + /** + * @param string $title + * @param string $ns + * @return eResponse + */ + function appendTitle($title, $ns = 'default') + { + if(empty($title)) + { + return $this; + } + if(!is_string($ns) || empty($ns)) + { + $ns = 'default'; + } + elseif(!isset($this->_title[$ns])) + { + $this->_title[$ns] = array(); + } + $this->_title[$ns][] = (string) $title; + return $this; + } + + /** + * @param string $title + * @param string $ns + * @return eResponse + */ + function prependTitle($title, $ns = 'default') + { + if(empty($title)) + { + return $this; + } + if(!is_string($ns) || empty($ns)) + { + $ns = 'default'; + } + elseif(!isset($this->_title[$ns])) + { + $this->_title[$ns] = array(); + } + array_unshift($this->_title[$ns], $title); + return $this; + } + + /** + * Assemble title + * @param string $ns + * @param bool $reset + * @return string + */ + function getTitle($ns = 'default', $reset = false) + { + if(!is_string($ns) || empty($ns)) + { + $ret = implode($this->_title_separator, $this->_title['default']); + if($reset) + $this->_title['default'] = ''; + } + elseif(isset($this->_title[$ns])) + { + $ret = implode($this->_title_separator, $this->_title[$ns]); + if($reset) + unset($this->_title[$ns]); + } + else + { + $ret = ''; + } + return $ret; + } + + /** + * + * @param string $render_mod + * @param mixed $ns + * @return eResponse + */ + function setRenderMod($render_mod, $ns = 'default') + { + $this->_render_mod[$ns] = $render_mod; + return $this; + } + + /** + * Retrieve render mod + * @param mixed $ns + * @return mixed + */ + function getRenderMod($ns = 'default') + { + if(!is_string($ns) || empty($ns)) + { + $ns = 'default'; + } + return vartrue($this->_render_mod[$ns], null); + } + + /** + * Generic meta information + * Example usage: + * addMeta('og:title', 'My Title'); + * addMeta(null, 30, array('http-equiv' => 'refresh')); + * addMeta(null, null, array('http-equiv' => 'refresh', 'content' => 30)); // same as above + * @param string $name 'name' attribute value, or null to avoid it + * @param string $content 'content' attribute value, or null to avoid it + * @param array $extended format 'attribute_name' => 'value' + * @return eResponse + */ + public function addMeta($name = null, $content = null, $extended = array()) + { + if(empty($content)){ return $this; } // content is required, otherwise ignore. + + //TODO need an option that allows subsequent entries to overwrite existing ones. + //ie. 'description' and 'keywords' should never be duplicated, but overwritten by plugins and other non-pref-based meta data. + + $attr = array(); + + if(null !== $name) + { + // $key = (substr($name,0,3) == 'og:') ? 'property' : 'name'; + // $attr[$key] = $name; + if(!in_array($name, $this->_meta_name_only)) + { + $attr['property'] = $name; // giving both should be valid and avoid issues with FB and others. + } + + if(!in_array($name, $this->_meta_property_only)) + { + $attr['name'] = $name; + } + } + + + + if(null !== $content) $attr['content'] = $content; + if(!empty($extended)) + { + if(!empty($attr)) $attr = array_merge($attr, $extended); + else $attr = $extended; + } + + if(!empty($attr)) $this->_meta[] = $attr; + return $this; + } + + /** + * Render meta tags, registered via addMeta() method + * @return string + */ + public function renderMeta() + { + $attrData = ''; + + e107::getEvent()->trigger('system_meta_pre', $this->_meta); + + foreach ($this->_meta as $attr) + { + $attrData .= ' $v) + { + $attrData .= ' '.preg_replace('/[^\w\-]/', '', $p).'="'.str_replace(array('"', '<'), '', $v).'"'; + } + $attrData .= ' />'."\n"; + } + + return $attrData; + } + + /** + * Add meta title, description and keywords + * + * @param string $meta property name + * @param string $content meta content + * @return eResponse + */ + function addMetaData($meta, $content) + { + $meta = '_' . $meta; + if(isset($this->$meta) && !empty($content)) + { + $content = str_replace(array('&', '"', "'"), array('&', '', ''), $content); + $this->{$meta}[] = htmlspecialchars((string) $content, ENT_QUOTES, 'UTF-8'); + } + return $this; + } + + /** + * Get meta title, description and keywords + * + * @param string $meta property name + * @return string + */ + function getMetaData($meta, $separator = '') + { + $meta = '_' . $meta; + if(isset($this->$meta) && !empty($this->$meta)) + { + return implode($separator, $this->$meta); + } + return ''; + } + + + + /** + * Return an array of all meta data + * @return array + */ + function getMeta() + { + return $this->_meta; + } + + + /** + * @param string $title + * @return eResponse + */ + function addMetaTitle($title) + { + return $this->addMetaData('e_PAGETITLE', $title); + } + + function getMetaTitle() + { + return $this->getMetaData('e_PAGETITLE', $this->_meta_title_separator); + } + + /** + * @param string $description + * @return eResponse + */ + function addMetaDescription($description) + { + return $this->addMetaData('META_DESCRIPTION', $description); + } + + function getMetaDescription() + { + return $this->getMetaData('META_DESCRIPTION'); + } + + /** + * @param string $keywords + * @return eResponse + */ + function addMetaKeywords($keywords) + { + return $this->addMetaData('META_KEYWORDS', $keywords); + } + + function getMetaKeywords() + { + return $this->getMetaData('META_KEYWORDS', ','); + } + + /** + * Send e107 meta-data + * @return eResponse + */ + function sendMeta() + { + //HEADERF already included or meta content already sent + if(e_AJAX_REQUEST || defined('USER_AREA') || defined('e_PAGETITLE')) + return $this; + + if(!defined('e_PAGETITLE') && !empty($this->_e_PAGETITLE)) + { + define('e_PAGETITLE', $this->getMetaTitle()); + } + if(!defined('META_DESCRIPTION') && !empty($this->_META_DESCRIPTION)) + { + define('META_DESCRIPTION', $this->getMetaDescription()); + } + if(!defined('META_KEYWORDS') && !empty($this->_META_KEYWORDS)) + { + define('META_KEYWORDS', $this->getMetaKeywords()); + } + return $this; + } + + /** + * Send Response Output - default method + * TODO - ajax send, using js_manager + * @param string $ns namespace/segment + * @param bool $return + * @param bool $render_message append system messages + * @return null|string + */ + function send($ns = null, $return = true, $render_message = true) + { + $content = $this->getBody($ns, true); + $render = $this->getParam('render'); + $meta = $this->getParam('meta'); + + $this->sendContentType(); + + if($render_message) + { + $content = eMessage::getInstance()->render().$content; + } + + if($meta) + { + $this->sendMeta(); + } + + //render disabled by the controller + if(!$this->getRenderMod($ns)) + { + $render = false; + } + + if($render) + { + $render = e107::getRender(); + if($return) + { + return $render->tablerender($this->getTitle($ns, true), $content, $this->getRenderMod($ns), true); + } + else + { + $render->tablerender($this->getTitle($ns, true), $content, $this->getRenderMod($ns)); + return ''; + } + } + elseif($return) + { + return $content; + } + else + { + print $content; + return ''; + } + } + + /** + * Send AJAX Json Response Output - default method + * It's fully compatible with the core dialog.js + * @param array $override override output associative array (header, body and footer keys) + * @param string $ns namespace/segment + * @param bool $render_message append system messages + */ + function sendJson($override = array(), $ns = null, $render_message = true) + { + if(!$ns) $ns = 'default'; + + $content = $this->getBody($ns, true); + // separate render parameter for json response, false by default + $render = $this->getParam('jsonRender'); + if($render_message) + { + $content = eMessage::getInstance()->render().$content; + } + + //render disabled by the controller + if(!$this->getRenderMod($ns)) + { + $render = false; + } + + + $title = ''; + if(!$this->getParam('jsonNoTitle')) + { + $titleArray = $this->_title; + $title = isset($titleArray[$ns]) ? array_pop($titleArray[$ns]) : ''; + } + + if($render) + { + $render = e107::getRender(); + $content = $render->tablerender($this->getTitle($ns, true), $content, $this->getRenderMod($ns), true); + } + + $jshelper = e107::getJshelper(); + $override = array_merge(array( + 'header' => $title, + 'body' => $content, + 'footer' => $statusText, + ), $override); + echo $jshelper->buildJsonResponse($override); + $jshelper->sendJsonResponse(null); + } + + /** + * JS manager + * @return e_jsmanager + */ + function getJs() + { + return e107::getJs(); + } +} + +/** + * We move all generic helper functionallity here - a lot of candidates in e107 class + * + */ +class eHelper +{ + protected static $_classRegEx = '#[^\w\s\-]#'; + protected static $_idRegEx = '#[^\w\-]#'; + protected static $_styleRegEx = '#[^\w\s\-\.;:!]#'; + + public static function secureClassAttr($string) + { + return preg_replace(self::$_classRegEx, '', $string); + } + + public static function secureIdAttr($string) + { + $string = str_replace(array('/','_'),'-',$string); + return preg_replace(self::$_idRegEx, '', $string); + } + + public static function secureStyleAttr($string) + { + return preg_replace(self::$_styleRegEx, '', $string); + } + + public static function buildAttr($safeArray) + { + return http_build_query($safeArray, null, '&'); + } + + public static function formatMetaTitle($title) + { + $title = trim(str_replace(array('"', "'"), '', strip_tags(e107::getParser()->toHTML($title, TRUE)))); + return trim(preg_replace('/[\s,]+/', ' ', str_replace('_', ' ', $title))); + } + + public static function secureSef($sef) + { + return trim(preg_replace('/[^\w\pL\s\-+.,]+/u', '', strip_tags(e107::getParser()->toHTML($sef, TRUE)))); + } + + public static function formatMetaKeys($keywordString) + { + $keywordString = preg_replace('/[^\w\pL\s\-.,+]/u', '', strip_tags(e107::getParser()->toHTML($keywordString, TRUE))); + return trim(preg_replace('/[\s]?,[\s]?/', ',', str_replace('_', ' ', $keywordString))); + } + + public static function formatMetaDescription($descrString) + { + $descrString = preg_replace('/[\r]*\n[\r]*/', ' ', trim(str_replace(array('"', "'"), '', strip_tags(e107::getParser()->toHTML($descrString, TRUE))))); + return trim(preg_replace('/[\s]+/', ' ', str_replace('_', ' ', $descrString))); + } + + /** + * Convert title to valid SEF URL string + * Type ending with 'l' stands for 'to lowercase', ending with 'c' - 'to camel case' + * @param string $title + * @param string $type dashl|dashc|dash|underscorel|underscorec|underscore|plusl|plusc|plus|none + * @return mixed|string + */ + public static function title2sef($title, $type = null) + { + /*$char_map = array( + // Latin + 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A', 'Æ' => 'AE', 'Ç' => 'C', + 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', + 'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => 'O', 'Ő' => 'O', + 'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ű' => 'U', 'Ý' => 'Y', 'Þ' => 'TH', + 'ß' => 'ss', + 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 'å' => 'a', 'æ' => 'ae', 'ç' => 'c', + 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', + 'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ő' => 'o', + 'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ü' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th', + 'ÿ' => 'y', + // Latin symbols + '©' => '(c)', + // Greek + 'Α' => 'A', 'Β' => 'B', 'Γ' => 'G', 'Δ' => 'D', 'Ε' => 'E', 'Ζ' => 'Z', 'Η' => 'H', 'Θ' => '8', + 'Ι' => 'I', 'Κ' => 'K', 'Λ' => 'L', 'Μ' => 'M', 'Ν' => 'N', 'Ξ' => '3', 'Ο' => 'O', 'Π' => 'P', + 'Ρ' => 'R', 'Σ' => 'S', 'Τ' => 'T', 'Υ' => 'Y', 'Φ' => 'F', 'Χ' => 'X', 'Ψ' => 'PS', 'Ω' => 'W', + 'Ά' => 'A', 'Έ' => 'E', 'Ί' => 'I', 'Ό' => 'O', 'Ύ' => 'Y', 'Ή' => 'H', 'Ώ' => 'W', 'Ϊ' => 'I', + 'Ϋ' => 'Y', + 'α' => 'a', 'β' => 'b', 'γ' => 'g', 'δ' => 'd', 'ε' => 'e', 'ζ' => 'z', 'η' => 'h', 'θ' => '8', + 'ι' => 'i', 'κ' => 'k', 'λ' => 'l', 'μ' => 'm', 'ν' => 'n', 'ξ' => '3', 'ο' => 'o', 'π' => 'p', + 'ρ' => 'r', 'σ' => 's', 'τ' => 't', 'υ' => 'y', 'φ' => 'f', 'χ' => 'x', 'ψ' => 'ps', 'ω' => 'w', + 'ά' => 'a', 'έ' => 'e', 'ί' => 'i', 'ό' => 'o', 'ύ' => 'y', 'ή' => 'h', 'ώ' => 'w', 'ς' => 's', + 'ϊ' => 'i', 'ΰ' => 'y', 'ϋ' => 'y', 'ΐ' => 'i', + // Turkish + 'Ş' => 'S', 'İ' => 'I', 'Ç' => 'C', 'Ü' => 'U', 'Ö' => 'O', 'Ğ' => 'G', + 'ş' => 's', 'ı' => 'i', 'ç' => 'c', 'ü' => 'u', 'ö' => 'o', 'ğ' => 'g', + // Russian + 'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'Yo', 'Ж' => 'Zh', + 'З' => 'Z', 'И' => 'I', 'Й' => 'J', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O', + 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C', + 'Ч' => 'Ch', 'Ш' => 'Sh', 'Щ' => 'Sh', 'Ъ' => '', 'Ы' => 'Y', 'Ь' => '', 'Э' => 'E', 'Ю' => 'Yu', + 'Я' => 'Ya', + 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'yo', 'ж' => 'zh', + 'з' => 'z', 'и' => 'i', 'й' => 'j', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o', + 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c', + 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sh', 'ъ' => '', 'ы' => 'y', 'ь' => '', 'э' => 'e', 'ю' => 'yu', + 'я' => 'ya', + // Ukrainian + 'Є' => 'Ye', 'І' => 'I', 'Ї' => 'Yi', 'Ґ' => 'G', + 'є' => 'ye', 'і' => 'i', 'ї' => 'yi', 'ґ' => 'g', + // Czech + 'Č' => 'C', 'Ď' => 'D', 'Ě' => 'E', 'Ň' => 'N', 'Ř' => 'R', 'Š' => 'S', 'Ť' => 'T', 'Ů' => 'U', + 'Ž' => 'Z', + 'č' => 'c', 'ď' => 'd', 'ě' => 'e', 'ň' => 'n', 'ř' => 'r', 'š' => 's', 'ť' => 't', 'ů' => 'u', + 'ž' => 'z', + // Polish + 'Ą' => 'A', 'Ć' => 'C', 'Ę' => 'e', 'Ł' => 'L', 'Ń' => 'N', 'Ó' => 'o', 'Ś' => 'S', 'Ź' => 'Z', + 'Ż' => 'Z', + 'ą' => 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n', 'ó' => 'o', 'ś' => 's', 'ź' => 'z', + 'ż' => 'z', + // Latvian + 'Ā' => 'A', 'Č' => 'C', 'Ē' => 'E', 'Ģ' => 'G', 'Ī' => 'i', 'Ķ' => 'k', 'Ļ' => 'L', 'Ņ' => 'N', + 'Š' => 'S', 'Ū' => 'u', 'Ž' => 'Z', + 'ā' => 'a', 'č' => 'c', 'ē' => 'e', 'ģ' => 'g', 'ī' => 'i', 'ķ' => 'k', 'ļ' => 'l', 'ņ' => 'n', + 'š' => 's', 'ū' => 'u', 'ž' => 'z' + );*/ + + $tp = e107::getParser(); + + // issue #3245: strip all html and bbcode before processing + $title = $tp->toText($title); + + $title = $tp->toASCII($title); + + $title = str_replace(array('/',' ',","),' ',$title); + $title = str_replace(array("&","(",")"),'',$title); + $title = preg_replace('/[^\w\d\pL\s.-]/u', '', strip_tags(e107::getParser()->toHTML($title, TRUE))); + $title = trim(preg_replace('/[\s]+/', ' ', str_replace('_', ' ', $title))); + $title = str_replace(array(' - ',' -','- ','--'),'-',$title); // cleanup to avoid --- + + $words = str_word_count($title,1, '1234567890'); + + $limited = array_slice($words, 0, 14); // Limit number of words to 14. - any more and it ain't friendly. + + $title = implode(" ",$limited); + + if(null === $type) + { + $type = e107::getPref('url_sef_translate'); + } + + switch ($type) + { + case 'dashl': //dasherize, to lower case + return self::dasherize($tp->ustrtolower($title)); + break; + + case 'dashc': //dasherize, camel case + return self::dasherize(self::camelize($title, true, ' ')); + break; + + case 'dash': //dasherize + return self::dasherize($title); + break; + + case 'underscorel': ///underscore, to lower case + return self::underscore($tp->ustrtolower($title)); + break; + + case 'underscorec': ///underscore, camel case + return self::underscore(self::camelize($title, true, ' ')); + break; + + case 'underscore': ///underscore + return self::underscore($title); + break; + + case 'plusl': ///plus separator, to lower case + return str_replace(' ', '+', $tp->ustrtolower($title)); + break; + + case 'plusc': ///plus separator, to lower case + return str_replace(' ', '+', self::camelize($title, true, ' ')); + break; + + case 'plus': ///plus separator + return str_replace(' ', '+', $title); + break; + + case 'none': + default: + return $title; + break; + } + } + + /** + * Return a memory value formatted helpfully + * $dp overrides the number of decimal places displayed - realistically, only 0..3 are sensible + * FIXME e107->parseMemorySize() START + * - move here all e107 class ban/ip related methods + * - out of (integer) range case? + * 32 bit systems range: -2147483648 to 2147483647 + * 64 bit systems range: -9223372036854775808 9223372036854775807 + * {@link http://www.php.net/intval} + * FIXME e107->parseMemorySize() END + * + * @param integer $size + * @param integer $dp + * @return string formatted size + */ + public static function parseMemorySize($size, $dp = 2) + { + if (!$size) { $size = 0; } + if ($size < 4096) + { // Fairly arbitrary limit below which we always return number of bytes + return number_format($size, 0).CORE_LAN_B; + } + + $size = $size / 1024; + $memunit = CORE_LAN_KB; + + if ($size > 1024) + { /* 1.002 mb, etc */ + $size = $size / 1024; + $memunit = CORE_LAN_MB; + } + if ($size > 1024) + { /* show in GB if >1GB */ + $size = $size / 1024; + $memunit = CORE_LAN_GB; + } + if ($size > 1024) + { /* show in TB if >1TB */ + $size = $size / 1024; + $memunit = CORE_LAN_TB; + } + return (number_format($size, $dp).$memunit); + } + + /** + * Get the current memory usage of the code + * If $separator argument is null, raw data (array) will be returned + * + * @param null|string $separator + * @return string|array memory usage + */ + public static function getMemoryUsage($separator = '/') + { + $ret = array(); + if(function_exists("memory_get_usage")) + { + $ret[] = eHelper::parseMemorySize(memory_get_usage()); + // With PHP>=5.2.0, can show peak usage as well + if (function_exists("memory_get_peak_usage")) $ret[] = eHelper::parseMemorySize(memory_get_peak_usage(TRUE)); + } + else + { + $ret[] = 'Unknown'; + } + + return (null !== $separator ? implode($separator, $ret) : $ret); + } + + public static function camelize($str, $all = false, $space = '') + { + // clever recursion o.O + if($all) return self::camelize('-'.$str, false, $space); + + $tmp = explode('-', str_replace(array('_', ' '), '-', e107::getParser()->ustrtolower($str))); + return trim(implode($space, array_map('ucfirst', $tmp)), $space); + } + + public static function labelize($str, $space = ' ') + { + return self::camelize($str, true, ' '); + } + + public static function dasherize($str) + { + return str_replace(array('_', ' '), '-', $str); + } + + public static function underscore($str) + { + return str_replace(array('-', ' '), '_', $str); + } + + /** + * Parse generic shortcode parameter string + * Format expected: {SC=key=val&key1=val1...} + * Escape strings: \& => & + * + * @param string $parmstr + * @return array associative param array + */ + public static function scParams($parm) + { + if (!$parm) return array(); + if (!is_array($parm)) + { + $parm = str_replace('\&', '%%__amp__%%', $parm); + $parm = str_replace('&', '&', $parm); // clean when it comes from the DB + parse_str($parm, $parm); + foreach ($parm as $k => $v) + { + $parm[str_replace('%%__amp__%%', '&', $k)] = str_replace('%%__amp__%%', '\&', $v); + } + } + + return $parm; + } + + /** + * Parse shortcode parameter string of type 'dual parameters' - advanced, more complex and slower(!) case + * Format expected: {SC=name|key=val&key1=val1...} + * Escape strings: \| => | , \& => & and \& => & + * Return array is formatted like this: + * 1 => string|array (depends on $name2array value) containing first set of parameters; + * 2 => array containing second set of parameters; + * 3 => string containing second set of parameters; + * + * @param string $parmstr + * @param boolean $first2array If true, first key (1) of the returned array will be parsed to array as well + * @return array + */ + public static function scDualParams($parmstr, $first2array = false) + { + if (!$parmstr) return array(1 => '', 2 => array(), 3 => ''); + if (is_array($parmstr)) return $parmstr; + + $parmstr = str_replace('&', '&', $parmstr); // clean when it comes from the DB + $parm = explode('|', str_replace(array('\|', '\&', '\&'), array('%%__pipe__%%', '%%__ampamp__%%', '%%__amp__%%'), $parmstr), 2); + + $multi = str_replace('%%__pipe__%%', '|', $parm[0]); + if ($first2array) + { + parse_str($multi, $multi); + foreach ($multi as $k => $v) + { + $multi[str_replace(array('%%__ampamp__%%', '%%__amp__%%'), array('&', '&'), $k)] = str_replace(array('%%__ampamp__%%', '%%__amp__%%'), array('&', '&'), $v); + } + } + + if (varset($parm[1])) + { + // second paramater as a string - allow to be further passed to shortcodes + $parmstr = str_replace(array('%%__pipe__%%', '%%__ampamp__%%', '%%__amp__%%'), array('\|', '\&', '\&'), $parm[1]); + parse_str(str_replace('%%__pipe__%%', '|', $parm[1]), $params); + foreach ($params as $k => $v) + { + $params[str_replace(array('%%__ampamp__%%', '%%__amp__%%'), array('&', '&'), $k)] = str_replace(array('%%__ampamp__%%', '%%__amp__%%'), array('&', '&'), $v); + } + } + else + { + $parmstr = ''; + $params = array(); + } + + return array(1 => $multi, 2 => $params, 3 => $parmstr); + } + + + /** + * Remove Social Media Trackers from a $_GET array based on key matches. + * @param array $get + * @return array + */ + public static function removeTrackers($get = array()) + { + $trackers = array('fbclid','utm_source','utm_medium','utm_content','utm_campaign','elan'); + + foreach($trackers as $val) + { + if(isset($get[$val])) + { + unset($get[$val]); + } + } + + return $get; + + } + + +} diff --git a/e107_handlers/benchmark.php b/e107_handlers/benchmark.php index 5d0100b0f..4aeb95554 100644 --- a/e107_handlers/benchmark.php +++ b/e107_handlers/benchmark.php @@ -1,116 +1,116 @@ - start(); - * - * // Do something, e.g. loop 1000000 times - * - * // stop timer and check your e_LOG folder - * $bench->end()->logResult('myevent'); - * //OR print out the result (don't forget to stop the timer if used without the above line! - * $bench->printResult(); - * - */ -class e_benchmark -{ - protected $time_start; - protected $time_end; - - /** - * Constructor - */ - function __construct() - { - $this->time_end = $this->time_start = 0; - } - - /** - * Start timer - * @return benchmark - */ - public function start() - { - $this->time_start = microtime(true); - return $this; - } - - /** - * Stop timer - * @return benchmark - */ - public function end() - { - $this->time_end = microtime(true); - return $this; - } - - /** - * Calculate result - * @return integer - */ - public function result() - { - return ($this->time_end - $this->time_start); - } - - /** - * Write result to a file in system log - * @param string $id identifier of the current benchmark event e.g. 'thumbnail.create' - * @param string $heading additional data to be shown in the log (header) e.g. '[Some Event]' - * @param boolean $append overwrite or append to the log file - * @return benchmark - */ - public function logResult($id, $heading = '', $append = true) - { - file_put_contents(e_LOG.'Benchmark_'.$id.'.log', $this->formatData($heading), ($append ? FILE_APPEND : 0)); - return $this; - } - - /** - * Send result to the stdout - * - * @param string $heading - * @return string - */ - public function printResult($heading = '') - { - print('
'.$this->formatData($heading).'
'); - return $this; - } - - /** - * Format data for loging/printing - * - * @param string $heading - * @return string - */ - function formatData($heading) - { - $data = "------------- Log Start -------------\n".date('r')." ".$heading."\n"; - $data .= "Result: ".$this->result()." sec\n------------- Log End -------------\n\n"; - return $data; - } + start(); + * + * // Do something, e.g. loop 1000000 times + * + * // stop timer and check your e_LOG folder + * $bench->end()->logResult('myevent'); + * //OR print out the result (don't forget to stop the timer if used without the above line! + * $bench->printResult(); + * + */ +class e_benchmark +{ + protected $time_start; + protected $time_end; + + /** + * Constructor + */ + function __construct() + { + $this->time_end = $this->time_start = 0; + } + + /** + * Start timer + * @return benchmark + */ + public function start() + { + $this->time_start = microtime(true); + return $this; + } + + /** + * Stop timer + * @return benchmark + */ + public function end() + { + $this->time_end = microtime(true); + return $this; + } + + /** + * Calculate result + * @return integer + */ + public function result() + { + return ($this->time_end - $this->time_start); + } + + /** + * Write result to a file in system log + * @param string $id identifier of the current benchmark event e.g. 'thumbnail.create' + * @param string $heading additional data to be shown in the log (header) e.g. '[Some Event]' + * @param boolean $append overwrite or append to the log file + * @return benchmark + */ + public function logResult($id, $heading = '', $append = true) + { + file_put_contents(e_LOG.'Benchmark_'.$id.'.log', $this->formatData($heading), ($append ? FILE_APPEND : 0)); + return $this; + } + + /** + * Send result to the stdout + * + * @param string $heading + * @return string + */ + public function printResult($heading = '') + { + print('
'.$this->formatData($heading).'
'); + return $this; + } + + /** + * Format data for loging/printing + * + * @param string $heading + * @return string + */ + function formatData($heading) + { + $data = "------------- Log Start -------------\n".date('r')." ".$heading."\n"; + $data .= "Result: ".$this->result()." sec\n------------- Log End -------------\n\n"; + return $data; + } } \ No newline at end of file diff --git a/e107_handlers/e_marketplace.php b/e107_handlers/e_marketplace.php index 122f4b49e..cfbddecc2 100644 --- a/e107_handlers/e_marketplace.php +++ b/e107_handlers/e_marketplace.php @@ -1,1239 +1,1239 @@ -_adapter_name = $force === 'wsdl' ? 'wsdl' : 'xmlrpc'; - } - elseif(!class_exists('SoapClient')) $this->_adapter_name = 'xmlrpc'; - else - { - $this->_adapter_name = 'wsdl'; - } - - } - - /** - * Set authorization key - * @deprecated subject of removal - */ - public function generateAuthKey($username, $password) - { - if(trim($username) == '' || trim($password) == '') - { - return false; - } - $this->setAuthKey($this->makeAuthKey($username, $password, true)); - return $this; - } - - /** - * Set authorization key - * @deprecated subject of removal - */ - public function setAuthKey($authkey) - { - $this->adapter->setAuthKey($authkey); - return $this; - } - - public function hasAuthKey() - { - return $this->adapter->hasAuthKey(); - } - - /** - * Make authorization key from user credentials - * @deprecated subject of removal - */ - public function makeAuthKey($username, $password = '', $plain = false) - { - $now = gmdate('y-m-d H'); - if($plain && !empty($password)) $password = md5($password); - return sha1($username.$password.$now); - } - - - - /** - * Have the admin enter their e107.org login details in order to create the authorization key. - * @deprecated subject of removal - */ - public function renderLoginForm() - { - - $text = ' -
-
- - -
-
-
-
-
- Login -
- -
- -
- -
-
- -
- -
- -
-
- -
-
- -
-
- -
-
-
'; - - //TODO Use Form handler for INPUT tags. - //XXX TBD OR do we just redirect to the signup page on the website, in an iframe? - - $text .= ' -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
- -
-
-
-
-
-
- '; - - return $text; - } - - /** - * Retrieve currently used adapter - * @param e_marketplace_adapter_abstract - * @return \e_marketplace_adapter_abstract - */ - public function adapter() - { - if(null === $this->adapter) - { - $className = 'e_marketplace_adapter_'.$this->_adapter_name; - $this->adapter = new $className(); - } - return $this->adapter; - } - - /** - * Retrieve currently used adapter - * @param e_marketplace_adapter_abstract - */ - public function call($method, $data, $apply = true) - { - if(E107_DEBUG_LEVEL > 0) - { - e107::getDebug()->log("Calling e107.org using ".$this->_adapter_name." adapter"); - } - return $this->adapter()->call($method, $data, $apply); - } - - /** - * Adapter proxy - */ - public function download($id, $mode, $type) - { - return $this->adapter()->download($id, $mode, $type); - } - - /** - * Direct adapter()->call() execution - experimental stage - */ - public function __call($method, $arguments) - { - if(strpos($method, 'get') === 0 || strpos($method, 'do') === 0) - { - return $this->adapter()->call($method, $arguments); - } - throw new Exception("Error Processing Request", 10); - } - - - public function __destruct() - { - $this->adapter = null; - //echo "Adapter destroyed", PHP_EOL; - } - - - /** - * @param $data - e107.org plugin/theme feed data. - * @return bool|string - */ - public function getDownloadModal($type='plugin',$data) - { - - $url = false; - - if($type === 'plugin') - { - - if(empty($data['plugin_id'])) - { - - $srcData = array( - 'plugin_id' => $data['params']['id'], - 'plugin_folder' => $data['folder'], - 'plugin_price' => $data['price'], - 'plugin_mode' => $data['params']['mode'], - 'plugin_url' => $data['url'], - ); - } - else - { - $srcData = $data; - } - - $d = http_build_query($srcData,false,'&'); - - // if(deftrue('e_DEBUG_PLUGMANAGER')) - { - $url = e_ADMIN.'plugin.php?mode=online&action=download&src='.base64_encode($d); - } - // else - { - // $url = e_ADMIN.'plugin.php?mode=download&src='.base64_encode($d); - } - - - } - - if($type === 'theme') - { - $srcData = array( - 'id' => $data['params']['id'], - 'url' => $data['url'], - 'mode' => 'addon', - 'price' => $data['price'] - ); - - $d = http_build_query($srcData,false,'&'); - $url = e_ADMIN.'theme.php?mode=main&action=download&src='.base64_encode($d);//$url.'&action=download'; - - } - - - return $url; - - } - - - - - - public function getVersionList($type='plugin') - { - $cache = e107::getCache(); - $cache->setMD5('_', false); - - $tag = 'Versions_'.$type; - - if($data = $cache->retrieve($tag,(60 * 12), true, true)) - { - return e107::unserialize($data); - } - - // $mp = $this->getMarketplace(); - // $mp->generateAuthKey($e107SiteUsername, $e107SiteUserpass); - e107::getDebug()->log("Retrieving ".$type." version list from e107.org"); - - $xdata = $this->call('getList', array( - 'type' => $type, - 'params' => array('limit' => 200, 'search' => null, 'from' => 0) - )); - - $arr = array(); - - if(!empty($xdata['data'])) - { - - foreach($xdata['data'] as $row) - { - $k = $row['folder']; - $arr[$k] = $row; - } - - } - - - if(empty($arr)) - { - $arr = array('-unable-to-connect'); // make sure something is cached so further lookups stop. - } - - $data = e107::serialize($arr, 'json'); - $cache->set($tag, $data, true, true, true); - - return $arr; - - } - - - -} - -abstract class e_marketplace_adapter_abstract -{ - /** - * e107.org download URL - * @var string - */ - protected $downloadUrl = 'https://e107.org/request/'; - - /** - * e107.org service URL [adapter implementation required] - * @var string - */ - protected $serviceUrl = null; - - /** - * Request method POST || GET [adapter implementation required] - * @var string - */ - public $requestMethod = null; - - - /** - * @var eAuth - */ - protected $_auth = null; - - /** - * e107.org authorization key - * @deprecated subject of removal - * @var string - */ - protected $authKey = null; - - abstract public function test($input); - //abstract public function call($method, $data, $apply); - abstract public function call($method, $data, $apply = true); // Fix issue #490 - abstract public function fetch($method, &$result); - - /** - * Authorization object - * @return eAuth - */ - public function auth() - { - if(null === $this->_auth) - { - $this->_auth = new eAuth; - $this->_auth->loadSysCredentials(); - $this->_auth->requestMethod = $this->requestMethod; - } - return $this->_auth; - } - - /** - * Set authorization key - * @deprecated subject of removal - */ - public function setAuthKey($authkey) - { - $this->authKey = $authkey; - return $this; - } - - /** - * @deprecated subject of removal - */ - public function hasAuthKey() - { - return ($this->authKey !== null) ? true : false; - } - - /** - * @deprecated subject of removal - */ - public function getAuthKey() - { - return $this->authKey; - } - - - /** - * Download a Plugin or Theme to Temp, then test and move to plugin/theme folder and backup to system backup folder. - * XXX better way to return status (e.g. getError(), getStatus() service call before download) - * XXX temp is not well cleaned - * XXX themes/plugins not well tested after unzip (example - Headline 1.0, non-default structure, same applies to most FS net free themes) - * This method is direct outputting the status. If not needed - use buffer - * @param string $remotefile URL - * @param string $type plugin or theme - */ - public function download($id, $mode, $type) - { - $tp = e107::getParser(); - $mes = e107::getMessage(); - $fl = e107::getFile(); - - $id = intval($id); - $qry = 'id='.$id.'&type='.$type.'&mode='.$mode; - $remotefile = $this->downloadUrl."?auth=".$this->getAuthKey()."&".$qry; - - $localfile = md5($remotefile.time()).".zip"; - $mes->addSuccess(TPVLAN_81); - - // FIXME call the service, check status first, then download (if status OK), else retireve the error break and show it - - $result = $this->getRemoteFile($remotefile, $localfile); - - if(!$result) - { - if(filesize(e_TEMP.$localfile)) - { - $contents = file_get_contents(e_TEMP.$localfile); - $contents = explode('REQ_', $contents); - $mes->addError('[#'.trim($contents[1]).'] '.trim($contents[0])); flush(); - } - - @unlink(e_TEMP.$localfile); - return false; - } - - - if(!file_exists(e_TEMP.$localfile)) - { - $srch = array("[", "]"); - $repl = array("", ""); - - $mes->addError( TPVLAN_83." ".str_replace($srch, $repl, TPVLAN_84)); - - if(E107_DEBUG_LEVEL > 0) - { - $mes->addDebug('local='.$localfile); // ; flush(); - } - - return false; - } - - - if($fl->unzipArchive($localfile,$type, true)) - { - $mes->addSuccess(TPVLAN_82); - return true; - } - else - { - $mes->addSuccess( "".TPVLAN_84.""); - } - - return false; - } - - - - // Grab a remote file and save it in the /temp directory. requires CURL - function getRemoteFile($remote_url, $local_file, $type='temp') - { - // FIXME - different methods (see xml handler getRemoteFile()), error handling, appropriate error messages, - if (!function_exists("curl_init")) - { - return false; - } - $path = ($type == 'media') ? e_MEDIA : e_TEMP; - - $fp = fopen($path.$local_file, 'w'); // media-directory is the root. - //$fp1 = fopen(e_TEMP.'/curllog.txt', 'w'); - - - $cp = e107::getFile()->initCurl($remote_url); - curl_setopt($cp, CURLOPT_FILE, $fp); - /* $cp = curl_init($remote_url); - - - //curl_setopt($ch, CURLOPT_VERBOSE, 1); - //curl_setopt($ch, CURLOPT_STDERR, $fp1); - - curl_setopt($cp, CURLOPT_REFERER, e_REQUEST_HTTP); - curl_setopt($cp, CURLOPT_HEADER, 0); - curl_setopt($cp, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"); - curl_setopt($cp, CURLOPT_COOKIEFILE, e_SYSTEM.'cookies.txt');*/ - - $buffer = curl_exec($cp); - - curl_close($cp); - fclose($fp); - //fclose($fp1); - - if($buffer) - { - $size = filesize($path.$local_file); - if($size < 400) $buffer = false; - } - - return ($buffer) ? true : false; - } -} - -class e_marketplace_adapter_wsdl extends e_marketplace_adapter_abstract -{ - /** - * e107.org WSDL URL - * @var string - */ - protected $serviceUrl = 'https://e107.org/service?wsdl'; - - /** - * Request method POST || GET - * @var string - */ - public $requestMethod = 'POST'; - - /** - * Soap client instance - * @var SoapClient - */ - protected $client = null; - - public function __construct() - { - e107_ini_set('soap.wsdl_cache_enabled', 0); - e107_ini_set('soap.wsdl_cache_ttl', 0); - - $options = array( - "trace" => true, - 'exception' => true, - "uri" => "http://server.soap.e107.inc.com/", - 'cache_wsdl' => WSDL_CACHE_NONE, - 'connection_timeout' => 5, - ); - - - try - { - //libxml_disable_entity_loader(false); - $this->client = new SoapClient($this->serviceUrl, $options); - } - catch (Exception $e) - { - $message = deftrue('LAN_ERROR_CONNECTION', "Unable to connect for updates. Please check firewall and/or internet connection."); - e107::getMessage()->addInfo($message); - e107::getMessage()->addDebug($e->getMessage()); - } - - - - if(function_exists('xdebug_disable')) - { - xdebug_disable(); - } - } - - public function test($input) - { - try - { - $res = $this->client->get_echo($input); - } - catch(Exception $e) - { - $res = $e->getMessage(); - } - return $res; - - } - - /** - * Generic call method - */ - public function _call($method, $args, $apply = true) - { - $result = array( - 'data' => null, - //'error'=> array('code' => 0, 'message' => null) - ); - $ret = null; - - // authorize on every call, service class decides what to do on every method call - $auth = new stdClass; - $auth->authKey = $this->getAuthKey(); - $header = new SoapHeader('https://e107.org/services/auth', 'checkAuthHeader', $auth); - - if(!is_object($this->client)) - { - $result['exception'] = array(); - $result['exception']['message'] = "Unable to connect at this time."; - return $result; - } - - try - { - - - $this->client->__setSoapHeaders(array($header)); - if(is_array($args) && $apply) - { - $ret = call_user_func_array(array($this->client, $method), $args); - } - else $ret = $this->client->$method($args); - - $result = $ret; - if(isset($ret['exception'])) - { - $result['exception'] = array(); - $result['exception']['message'] = "API Exception [call::{$method}]: (#".$ret['exception']['code'].") ".$ret['exception']['message']; - $result['exception']['code'] = 'API_'.$ret['exception']['code']; - } - unset($ret); - } - catch(SoapFault $e) - { - $result['exception']['message'] = "SoapFault Exception [call::{$method}]: (#".$e->faultcode.") ".$e->faultstring; - $result['exception']['code'] = 'SOAP_'.$e->faultcode; - if(E107_DEBUG_LEVEL) - { - $result['exception']['trace'] = $e->getTraceAsString(); - $result['exception']['message'] .= ". Header fault: ".($e->headerfault ? $e->headerfault : 'n/a'); - } - } - catch(Exception $e) - { - $result['exception']['message'] = "Generic Exception [call::{$method}]: (#".$e->getCode().") ".$e->getMessage(); - $result['exception']['code'] = 'GEN_'.$e->getCode(); - if(E107_DEBUG_LEVEL) - { - $result['debug']['trace'] = $e->getTraceAsString(); - } - } - if(E107_DEBUG_LEVEL) - { - $result['debug']['response'] = $this->client->__getLastResponse(); - $result['debug']['request'] = $this->client->__getLastRequest(); - $result['debug']['request_header'] = $this->client->__getLastRequestHeaders(); - } - return $result; - } - - /** - * Public call method - */ - public function call($method, $data, $apply = true) - { - return $this->_call($method, $data, $apply); - } - - /** - * Prepare the result, not needed for WSDL - * SUBJECT OF REMOVAL - */ - public function fetch($method, &$result) - { - if(isset($result['error'])) - { - return $result; - } - - switch ($method) - { - case 'getList': - break; - } - return $result; - } - - public function __destruct() - { - $this->client = null; - //echo "SOAP Client destroyed", PHP_EOL; - } -} - -class e_marketplace_adapter_xmlrpc extends e_marketplace_adapter_abstract -{ - /** - * e107.org XML-rpc service - * @var xmlClass - */ - protected $serviceUrl = 'https://e107.org/xservice'; - - /** - * Request method POST || GET - * @var string - */ - public $requestMethod = 'GET'; - - protected $_forceArray = array(); - protected $_forceNumericalArray = array(); - - public function __construct() - { - } - - public function test($input) - { - - } - - public function call($method, $data, $apply = true) - { - $client = $this->client(); - - // settings based on current method - $this->prepareClient($method, $client); - - // authorization data - $data['auth'] = $this->getAuthKey(); - $data['action'] = $method; - - foreach($data['params'] as $k=>$v) - { - $data[$k] = $v; - } - unset($data['params']); - - - // build the request query - $qry = str_replace(array('s%5B', '%5D'), array('[', ']'), http_build_query($data, null, '&')); - $url = $this->serviceUrl.'?'.$qry; - $result = array(); - - // call it - try - { - $xmlString = $client->loadXMLfile($url,false); - $xml = new SimpleXMLIterator($xmlString); - //$result = $client->loadXMLfile($url, 'advanced'); - $result = $this->fetch($method, $xml); - if(isset($result['exception'])) - { - $exception = $result['exception']; - $result['exception'] = array(); - $result['exception']['message'] = "API Exception [call::{$method}]: (#".$exception['code'].") ".$exception['message']; - $result['exception']['code'] = 'API_'.$exception['code']; - } - } - catch(Exception $e) - { - $result['exception']['message'] = "Generic Exception [call::{$method}]: (#".$e->getCode().") ".$e->getMessage(); - $result['exception']['code'] = 'GEN_'.$e->getCode(); - } - return $result; - } - - public function fetch($method, &$result) - { - $ret = $this->parse($result); - $this->fetchParams($ret); - - switch ($method) - { - // normalize - case 'getList': - $ret['data'] = $ret['data']['item']; - break; - } - return $ret; - } - - /** - * New experimental XML parser, will be moved to XML handlers soon - * XXX replace xmlClass::xml2array() after this one passes all tests - * @param SimpleXmlIterator $xml - * @param string $parentName parent node name - used currently for debug only - * @return array|string - */ - public function parse($xml, $parentName = null) - { - $ret = array(); - $tags = array_keys(get_object_vars($xml)); - $count = $xml->count(); - $tcount = count($tags); - - if($count === 0) - { - $attr = (array) $xml->attributes(); - if(!empty($attr)) - { - $ret['@attributes'] = $attr['@attributes']; - $ret['@value'] = (string) $xml; - $ret['@value'] = trim($ret['@value']); - } - else - { - $ret = (string) $xml; - $ret = trim($ret); - } - return $ret; - } - - /** - * - * - * - * - */ - if($tcount === 1 && $count > 1) - { - foreach ($xml as $name => $node) - { - $_res = $this->parse($node, $name); - if(is_string($_res)) - { - $_res = trim($_res); - } - - $ret[$name][] = $this->parse($node, $name); - } - } - // default - else - { - foreach ($xml as $name => $node) - { - if(in_array($name, $this->_forceArray)) - { - $_res = $this->parse($node, $name); - if(is_string($_res)) $_res = trim($_res); - - if(empty($_res)) $ret[$name] = array(); // empty - elseif(is_string($_res)) $ret[$name][] = $_res; // string - else - { - if(in_array($name, $this->_forceNumericalArray)) $ret[$name][] = $_res; //array - controlled force numerical array - else $ret[$name] = $_res; //array, no force - } - } - else $ret[$name] = $this->parse($node, $name); - } - } - - - $attr = (array) $xml->attributes(); - if(!empty($attr)) - { - $ret['@attributes'] = $attr['@attributes']; - } - - return $ret; - } - - /** - * Normalize parameters/attributes - * @param array $result parsed to array XML response data - */ - public function fetchParams(&$result) - { - foreach ($result as $tag => $data) - { - if($tag === 'params') - { - foreach ($data['param'] as $i => $param) - { - $result[$tag][$param['@attributes']['name']] = $param['@value']; - unset($result[$tag]['param'][$i]); - } - unset($result[$tag]['param']); - } - elseif($tag === 'exception') - { - $result['exception'] = array('code' => (int) $result['exception']['@attributes']['code'], 'message' => $result['exception']['@value']); - //unset($result['exception']); - } - elseif($tag === '@attributes') - { - $result['params'] = $result['@attributes']; - unset($result['@attributes']); - } - elseif(is_array($result[$tag])) - { - $this->fetchParams($result[$tag]); - } - } - } - - /** - * @param string $method - * @param xmlClass $client - */ - public function prepareClient($method, &$client) - { - switch ($method) - { - case 'getList': - $this->_forceArray = array('item', 'screenshots', 'image'); - $this->_forceNumericalArray = array('item', 'image'); - //$client->setOptArrayTags('item,screenshots,image') - // ->setOptStringTags('icon,folder,version,author,authorURL,date,compatibility,url,thumbnail,featured,livedemo,price,name,description,category,image'); - break; - } - } - - /** - * @return xmlClass - */ - public function client() - { - return e107::getXml(false); - } -} - -class eAuth -{ - - /** - * e107.org manage client credentials (Consumer Key and Secret) URL - * @var string - */ - protected $eauthConsumerUrl = 'https://e107.org/eauth/client'; - - /** - * URL used to make temporary credential request (Request Token and Secret) to e107.org before the authorization phase - * @var string - */ - protected $eauthRequestUrl = 'https://e107.org/eauth/initialize'; - - /** - * URL used to redirect and authorize the resource owner (user) on e107.org using temporary (request) token - * @var string - */ - protected $eauthAuthorizeUrl = 'https://e107.org/eauth/authorize'; - - /** - * URL used to obtain token credentials (Access Token and Secret) from e107.org using temporary (request) token - * @var string - */ - protected $eauthAccessUrl = 'https://e107.org/eauth/token'; - - /** - * Public client key (generated and obtained from e107.org) - * @var string - */ - public $eauthConsumerKey = null; - - /** - * Client shared secret (generated and obtained from e107.org) - * @var string - */ - public $eauthConsumerSecret = null; - - /** - * Public temporary request token (generated and obtained from e107.org) - * @var string - */ - public $eauthRequestKey = null; - - /** - * Temporary request shared secret (generated and obtained from e107.org) - * @var string - */ - public $eauthRequestSecret = null; - - /** - * Public access token (generated and obtained from e107.org) - * @var string - */ - public $eauthAccessToken = null; - - /** - * Access shared secret (generated and obtained from e107.org) - * @var string - */ - public $eauthAccessSecret = null; - - /** - * Request method POST || GET - * @var string - */ - public $requestMethod = null; - - public function isClient() - { - $this->loadSysCredentials(); - return (!empty($this->eauthConsumerKey) && !empty($this->eauthConsumerSecret)); - } - - public function isInitialized() - { - $this->loadSysCredentials(); - return ($this->isClient() && !empty($this->eauthRequestKey) && !empty($this->eauthRequestSecret)); - } - - public function hasAccess() - { - $this->loadSysCredentials(); - return ($this->isClient() && !empty($this->eauthAccessToken) && !empty($this->eauthAccessSecret)); - } - - public function serviceAuthData($method, $args, $toObject = true) - { - // The client has previously registered with the server and obtained the client identifier dpf43f3p2l4k3l03 and client secret kd94hf93k423kf44. - // It has executed the eAuth workflow and obtained an access token nnch734d00sl2jdk and token secret pfkkdhi9sl3r4s00 - - $date = gmdate('Y-m-d H:i:s'); - $timestamp = $this->gmtTime($date); - $nonce = $this->nonce($timestamp); // create nonce - - $cryptMethod = $this->cryptMethod(); - $authData = array( - 'eauth_consumer_key' => $this->eauthConsumerKey, // (Client Identifier) Application key - 'eauth_token' => $this->eauthAccessToken, // Access Token - 'eauth_nonce' => $nonce,//'kllo9940pd9333jh' 'nonce' (number used once) string - 'eauth_timestamp' => $timestamp, // timestamp - 'eauth_signature_method'=> $cryptMethod, // encryption method - 'eauth_version' => '1.0', // signature method - ); - - // current request parameters - $args['action'] = $method; - - // signature data for building the signature - $signatureData = $authData; - - // add request parameters to the signature array - $signatureData['eauth_request_params'] = $args; - - // sort all - self::array_kmultisort($signatureData); - - // signature base string - $signatureBaseString = $this->requestMethod.'&'.rawurlencode($this->serviceUrl).'&'.http_build_query($signatureData, false, '&'); - $secretKey = rawurlencode($this->eauthConsumerSecret).'&'.rawurlencode($this->eauthAccessSecret); - - // crypt it - $signature = $this->crypt($signatureBaseString, $secretKey); - - //encode it - $authData['eauth_signature'] = base64_encode($signature); - if($toObject) return self::toObject($authData); - - return $authData; - } - - - public static function toObject($array) - { - $obj = new stdClass; - foreach ($array as $key => $value) - { - $obj->$key = $value; - } - return $obj; - } - - /** - * Load credentials stored in a system file - * @param boolean $force - * @return e_marketplace_adapter_abstract adapter instance - */ - public function loadSysCredentials($force = false) - { - if($force || null === $this->eauthConsumerKey) - { - $data = e107::getArrayStorage()->load('eauth'); - if(empty($data)) $data = array(); - $this->eauthConsumerKey = varset($data['consumer_key'], ''); - $this->eauthConsumerSecret = varset($data['consumer_secret'], ''); - $this->eauthAccessToken = varset($data['access_token'], ''); - $this->eauthAccessSecret = varset($data['access_secret'], ''); - } - return $this; - } - - public function storeSysCredentials($credentials = null) - { - if(null === $credentials) - { - $credentials = array( - 'consumer_key' => $this->eauthConsumerKey, - 'consumer_secret' => $this->eauthConsumerSecret, - 'access_token' => $this->eauthAccessToken, - 'access_secret' => $this->eauthAccessSecret, - ); - } - if(!is_array($credentials)) return false; - - foreach ($credentials as $key => $value) - { - switch ($key) - { - case 'consumer_key': - case 'consumer_secret': - case 'access_token': - case 'access_secret': - // OK - break; - - default: - unset($credentials[$key]); - break; - } - } - - return e107::getArrayStorage()->store($credentials, 'eauth'); - } - - /** - * Retrieve available system credentials or credential value - * @param string $key [optional] - * return mixed array of all credentials or string credential value - */ - public function getCredentials($key = null) - { - $this->loadSysCredentials(); - - $credentials = array( - 'consumer_key' => $this->eauthConsumerKey, - 'consumer_secret' => $this->eauthConsumerSecret, - 'access_token' => $this->eauthAccessToken, - 'access_secret' => $this->eauthAccessSecret, - ); - if(null !== $key) return varset($credentials[$key], null); - return $credentials; - } - - public function toAuthHeader($params) - { - $first = true; - $realm = isset($params['realm']) ? $params['realm'] : null; - if($realm) - { - $out = 'Authorization: eAuth realm="'.rawurlencode($realm).'"'; - $first = false; - } - else - $out = 'Authorization: eAuth'; - - $total = array(); - foreach($params as $k => $v) - { - if(substr($k, 0, 5) != "eauth") continue; - if(is_array($v)) - { - throw new Exception('Arrays not supported in headers', 200); - } - $out .= ($first) ? ' ' : ','; - $out .= rawurlencode($k).'="'.rawurlencode($v).'"'; - $first = false; - } - return $out; - } - - - public function cryptMethod() - { - return function_exists('hash_hmac') ? 'HMAC-SHA1' : 'SHA1'; - } - - function random($bits = 256) - { - $bytes = ceil($bits / 8); - $ret = ''; - for ($i = 0; $i < $bytes; $i++) - { - $ret .= chr(mt_rand(0, 255)); - } - return $ret; - } - - public function crypt($string, $secretKey) - { - $cMethod = $this->cryptMethod(); - // Append secret if it's sha1 - if($cMethod == 'SHA1') - { - return sha1($string.$secretKey); - } - // use secret key if HMAC-SHA1 - return hash_hmac('sha1', $string, $secretKey); - } - - public function nonce($timestamp) - { - return $this->crypt($this->random().$timestamp, $this->eauthAccessSecret.$this->eauthConsumerSecret); - } - - public function gmtTime($string) - { - $ret = false; - // mask - Y-m-d H:i:s - if(preg_match('#(.*?)-(.*?)-(.*?) (.*?):(.*?):(.*?)$#', $string, $matches)) - { - $ret = gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]); - } - return $ret; - } - - public static function array_kmultisort(&$array, $order = 'asc') - { - $func = $order == 'asc' ? 'ksort' : 'krsort'; - $func($array); - foreach ($array as $key => $value) - { - if(is_array($value)) - { - self::array_kmultisort($value, $order); - $array[$key] = $value; - } - } - } -} +_adapter_name = $force === 'wsdl' ? 'wsdl' : 'xmlrpc'; + } + elseif(!class_exists('SoapClient')) $this->_adapter_name = 'xmlrpc'; + else + { + $this->_adapter_name = 'wsdl'; + } + + } + + /** + * Set authorization key + * @deprecated subject of removal + */ + public function generateAuthKey($username, $password) + { + if(trim($username) == '' || trim($password) == '') + { + return false; + } + $this->setAuthKey($this->makeAuthKey($username, $password, true)); + return $this; + } + + /** + * Set authorization key + * @deprecated subject of removal + */ + public function setAuthKey($authkey) + { + $this->adapter->setAuthKey($authkey); + return $this; + } + + public function hasAuthKey() + { + return $this->adapter->hasAuthKey(); + } + + /** + * Make authorization key from user credentials + * @deprecated subject of removal + */ + public function makeAuthKey($username, $password = '', $plain = false) + { + $now = gmdate('y-m-d H'); + if($plain && !empty($password)) $password = md5($password); + return sha1($username.$password.$now); + } + + + + /** + * Have the admin enter their e107.org login details in order to create the authorization key. + * @deprecated subject of removal + */ + public function renderLoginForm() + { + + $text = ' +
+
+ + +
+
+
+
+
+ Login +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+
'; + + //TODO Use Form handler for INPUT tags. + //XXX TBD OR do we just redirect to the signup page on the website, in an iframe? + + $text .= ' +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+
+
+
+
+ '; + + return $text; + } + + /** + * Retrieve currently used adapter + * @param e_marketplace_adapter_abstract + * @return \e_marketplace_adapter_abstract + */ + public function adapter() + { + if(null === $this->adapter) + { + $className = 'e_marketplace_adapter_'.$this->_adapter_name; + $this->adapter = new $className(); + } + return $this->adapter; + } + + /** + * Retrieve currently used adapter + * @param e_marketplace_adapter_abstract + */ + public function call($method, $data, $apply = true) + { + if(E107_DEBUG_LEVEL > 0) + { + e107::getDebug()->log("Calling e107.org using ".$this->_adapter_name." adapter"); + } + return $this->adapter()->call($method, $data, $apply); + } + + /** + * Adapter proxy + */ + public function download($id, $mode, $type) + { + return $this->adapter()->download($id, $mode, $type); + } + + /** + * Direct adapter()->call() execution - experimental stage + */ + public function __call($method, $arguments) + { + if(strpos($method, 'get') === 0 || strpos($method, 'do') === 0) + { + return $this->adapter()->call($method, $arguments); + } + throw new Exception("Error Processing Request", 10); + } + + + public function __destruct() + { + $this->adapter = null; + //echo "Adapter destroyed", PHP_EOL; + } + + + /** + * @param $data - e107.org plugin/theme feed data. + * @return bool|string + */ + public function getDownloadModal($type='plugin',$data) + { + + $url = false; + + if($type === 'plugin') + { + + if(empty($data['plugin_id'])) + { + + $srcData = array( + 'plugin_id' => $data['params']['id'], + 'plugin_folder' => $data['folder'], + 'plugin_price' => $data['price'], + 'plugin_mode' => $data['params']['mode'], + 'plugin_url' => $data['url'], + ); + } + else + { + $srcData = $data; + } + + $d = http_build_query($srcData,false,'&'); + + // if(deftrue('e_DEBUG_PLUGMANAGER')) + { + $url = e_ADMIN.'plugin.php?mode=online&action=download&src='.base64_encode($d); + } + // else + { + // $url = e_ADMIN.'plugin.php?mode=download&src='.base64_encode($d); + } + + + } + + if($type === 'theme') + { + $srcData = array( + 'id' => $data['params']['id'], + 'url' => $data['url'], + 'mode' => 'addon', + 'price' => $data['price'] + ); + + $d = http_build_query($srcData,false,'&'); + $url = e_ADMIN.'theme.php?mode=main&action=download&src='.base64_encode($d);//$url.'&action=download'; + + } + + + return $url; + + } + + + + + + public function getVersionList($type='plugin') + { + $cache = e107::getCache(); + $cache->setMD5('_', false); + + $tag = 'Versions_'.$type; + + if($data = $cache->retrieve($tag,(60 * 12), true, true)) + { + return e107::unserialize($data); + } + + // $mp = $this->getMarketplace(); + // $mp->generateAuthKey($e107SiteUsername, $e107SiteUserpass); + e107::getDebug()->log("Retrieving ".$type." version list from e107.org"); + + $xdata = $this->call('getList', array( + 'type' => $type, + 'params' => array('limit' => 200, 'search' => null, 'from' => 0) + )); + + $arr = array(); + + if(!empty($xdata['data'])) + { + + foreach($xdata['data'] as $row) + { + $k = $row['folder']; + $arr[$k] = $row; + } + + } + + + if(empty($arr)) + { + $arr = array('-unable-to-connect'); // make sure something is cached so further lookups stop. + } + + $data = e107::serialize($arr, 'json'); + $cache->set($tag, $data, true, true, true); + + return $arr; + + } + + + +} + +abstract class e_marketplace_adapter_abstract +{ + /** + * e107.org download URL + * @var string + */ + protected $downloadUrl = 'https://e107.org/request/'; + + /** + * e107.org service URL [adapter implementation required] + * @var string + */ + protected $serviceUrl = null; + + /** + * Request method POST || GET [adapter implementation required] + * @var string + */ + public $requestMethod = null; + + + /** + * @var eAuth + */ + protected $_auth = null; + + /** + * e107.org authorization key + * @deprecated subject of removal + * @var string + */ + protected $authKey = null; + + abstract public function test($input); + //abstract public function call($method, $data, $apply); + abstract public function call($method, $data, $apply = true); // Fix issue #490 + abstract public function fetch($method, &$result); + + /** + * Authorization object + * @return eAuth + */ + public function auth() + { + if(null === $this->_auth) + { + $this->_auth = new eAuth; + $this->_auth->loadSysCredentials(); + $this->_auth->requestMethod = $this->requestMethod; + } + return $this->_auth; + } + + /** + * Set authorization key + * @deprecated subject of removal + */ + public function setAuthKey($authkey) + { + $this->authKey = $authkey; + return $this; + } + + /** + * @deprecated subject of removal + */ + public function hasAuthKey() + { + return ($this->authKey !== null) ? true : false; + } + + /** + * @deprecated subject of removal + */ + public function getAuthKey() + { + return $this->authKey; + } + + + /** + * Download a Plugin or Theme to Temp, then test and move to plugin/theme folder and backup to system backup folder. + * XXX better way to return status (e.g. getError(), getStatus() service call before download) + * XXX temp is not well cleaned + * XXX themes/plugins not well tested after unzip (example - Headline 1.0, non-default structure, same applies to most FS net free themes) + * This method is direct outputting the status. If not needed - use buffer + * @param string $remotefile URL + * @param string $type plugin or theme + */ + public function download($id, $mode, $type) + { + $tp = e107::getParser(); + $mes = e107::getMessage(); + $fl = e107::getFile(); + + $id = intval($id); + $qry = 'id='.$id.'&type='.$type.'&mode='.$mode; + $remotefile = $this->downloadUrl."?auth=".$this->getAuthKey()."&".$qry; + + $localfile = md5($remotefile.time()).".zip"; + $mes->addSuccess(TPVLAN_81); + + // FIXME call the service, check status first, then download (if status OK), else retireve the error break and show it + + $result = $this->getRemoteFile($remotefile, $localfile); + + if(!$result) + { + if(filesize(e_TEMP.$localfile)) + { + $contents = file_get_contents(e_TEMP.$localfile); + $contents = explode('REQ_', $contents); + $mes->addError('[#'.trim($contents[1]).'] '.trim($contents[0])); flush(); + } + + @unlink(e_TEMP.$localfile); + return false; + } + + + if(!file_exists(e_TEMP.$localfile)) + { + $srch = array("[", "]"); + $repl = array("", ""); + + $mes->addError( TPVLAN_83." ".str_replace($srch, $repl, TPVLAN_84)); + + if(E107_DEBUG_LEVEL > 0) + { + $mes->addDebug('local='.$localfile); // ; flush(); + } + + return false; + } + + + if($fl->unzipArchive($localfile,$type, true)) + { + $mes->addSuccess(TPVLAN_82); + return true; + } + else + { + $mes->addSuccess( "".TPVLAN_84.""); + } + + return false; + } + + + + // Grab a remote file and save it in the /temp directory. requires CURL + function getRemoteFile($remote_url, $local_file, $type='temp') + { + // FIXME - different methods (see xml handler getRemoteFile()), error handling, appropriate error messages, + if (!function_exists("curl_init")) + { + return false; + } + $path = ($type == 'media') ? e_MEDIA : e_TEMP; + + $fp = fopen($path.$local_file, 'w'); // media-directory is the root. + //$fp1 = fopen(e_TEMP.'/curllog.txt', 'w'); + + + $cp = e107::getFile()->initCurl($remote_url); + curl_setopt($cp, CURLOPT_FILE, $fp); + /* $cp = curl_init($remote_url); + + + //curl_setopt($ch, CURLOPT_VERBOSE, 1); + //curl_setopt($ch, CURLOPT_STDERR, $fp1); + + curl_setopt($cp, CURLOPT_REFERER, e_REQUEST_HTTP); + curl_setopt($cp, CURLOPT_HEADER, 0); + curl_setopt($cp, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"); + curl_setopt($cp, CURLOPT_COOKIEFILE, e_SYSTEM.'cookies.txt');*/ + + $buffer = curl_exec($cp); + + curl_close($cp); + fclose($fp); + //fclose($fp1); + + if($buffer) + { + $size = filesize($path.$local_file); + if($size < 400) $buffer = false; + } + + return ($buffer) ? true : false; + } +} + +class e_marketplace_adapter_wsdl extends e_marketplace_adapter_abstract +{ + /** + * e107.org WSDL URL + * @var string + */ + protected $serviceUrl = 'https://e107.org/service?wsdl'; + + /** + * Request method POST || GET + * @var string + */ + public $requestMethod = 'POST'; + + /** + * Soap client instance + * @var SoapClient + */ + protected $client = null; + + public function __construct() + { + e107_ini_set('soap.wsdl_cache_enabled', 0); + e107_ini_set('soap.wsdl_cache_ttl', 0); + + $options = array( + "trace" => true, + 'exception' => true, + "uri" => "http://server.soap.e107.inc.com/", + 'cache_wsdl' => WSDL_CACHE_NONE, + 'connection_timeout' => 5, + ); + + + try + { + //libxml_disable_entity_loader(false); + $this->client = new SoapClient($this->serviceUrl, $options); + } + catch (Exception $e) + { + $message = deftrue('LAN_ERROR_CONNECTION', "Unable to connect for updates. Please check firewall and/or internet connection."); + e107::getMessage()->addInfo($message); + e107::getMessage()->addDebug($e->getMessage()); + } + + + + if(function_exists('xdebug_disable')) + { + xdebug_disable(); + } + } + + public function test($input) + { + try + { + $res = $this->client->get_echo($input); + } + catch(Exception $e) + { + $res = $e->getMessage(); + } + return $res; + + } + + /** + * Generic call method + */ + public function _call($method, $args, $apply = true) + { + $result = array( + 'data' => null, + //'error'=> array('code' => 0, 'message' => null) + ); + $ret = null; + + // authorize on every call, service class decides what to do on every method call + $auth = new stdClass; + $auth->authKey = $this->getAuthKey(); + $header = new SoapHeader('https://e107.org/services/auth', 'checkAuthHeader', $auth); + + if(!is_object($this->client)) + { + $result['exception'] = array(); + $result['exception']['message'] = "Unable to connect at this time."; + return $result; + } + + try + { + + + $this->client->__setSoapHeaders(array($header)); + if(is_array($args) && $apply) + { + $ret = call_user_func_array(array($this->client, $method), $args); + } + else $ret = $this->client->$method($args); + + $result = $ret; + if(isset($ret['exception'])) + { + $result['exception'] = array(); + $result['exception']['message'] = "API Exception [call::{$method}]: (#".$ret['exception']['code'].") ".$ret['exception']['message']; + $result['exception']['code'] = 'API_'.$ret['exception']['code']; + } + unset($ret); + } + catch(SoapFault $e) + { + $result['exception']['message'] = "SoapFault Exception [call::{$method}]: (#".$e->faultcode.") ".$e->faultstring; + $result['exception']['code'] = 'SOAP_'.$e->faultcode; + if(E107_DEBUG_LEVEL) + { + $result['exception']['trace'] = $e->getTraceAsString(); + $result['exception']['message'] .= ". Header fault: ".($e->headerfault ? $e->headerfault : 'n/a'); + } + } + catch(Exception $e) + { + $result['exception']['message'] = "Generic Exception [call::{$method}]: (#".$e->getCode().") ".$e->getMessage(); + $result['exception']['code'] = 'GEN_'.$e->getCode(); + if(E107_DEBUG_LEVEL) + { + $result['debug']['trace'] = $e->getTraceAsString(); + } + } + if(E107_DEBUG_LEVEL) + { + $result['debug']['response'] = $this->client->__getLastResponse(); + $result['debug']['request'] = $this->client->__getLastRequest(); + $result['debug']['request_header'] = $this->client->__getLastRequestHeaders(); + } + return $result; + } + + /** + * Public call method + */ + public function call($method, $data, $apply = true) + { + return $this->_call($method, $data, $apply); + } + + /** + * Prepare the result, not needed for WSDL + * SUBJECT OF REMOVAL + */ + public function fetch($method, &$result) + { + if(isset($result['error'])) + { + return $result; + } + + switch ($method) + { + case 'getList': + break; + } + return $result; + } + + public function __destruct() + { + $this->client = null; + //echo "SOAP Client destroyed", PHP_EOL; + } +} + +class e_marketplace_adapter_xmlrpc extends e_marketplace_adapter_abstract +{ + /** + * e107.org XML-rpc service + * @var xmlClass + */ + protected $serviceUrl = 'https://e107.org/xservice'; + + /** + * Request method POST || GET + * @var string + */ + public $requestMethod = 'GET'; + + protected $_forceArray = array(); + protected $_forceNumericalArray = array(); + + public function __construct() + { + } + + public function test($input) + { + + } + + public function call($method, $data, $apply = true) + { + $client = $this->client(); + + // settings based on current method + $this->prepareClient($method, $client); + + // authorization data + $data['auth'] = $this->getAuthKey(); + $data['action'] = $method; + + foreach($data['params'] as $k=>$v) + { + $data[$k] = $v; + } + unset($data['params']); + + + // build the request query + $qry = str_replace(array('s%5B', '%5D'), array('[', ']'), http_build_query($data, null, '&')); + $url = $this->serviceUrl.'?'.$qry; + $result = array(); + + // call it + try + { + $xmlString = $client->loadXMLfile($url,false); + $xml = new SimpleXMLIterator($xmlString); + //$result = $client->loadXMLfile($url, 'advanced'); + $result = $this->fetch($method, $xml); + if(isset($result['exception'])) + { + $exception = $result['exception']; + $result['exception'] = array(); + $result['exception']['message'] = "API Exception [call::{$method}]: (#".$exception['code'].") ".$exception['message']; + $result['exception']['code'] = 'API_'.$exception['code']; + } + } + catch(Exception $e) + { + $result['exception']['message'] = "Generic Exception [call::{$method}]: (#".$e->getCode().") ".$e->getMessage(); + $result['exception']['code'] = 'GEN_'.$e->getCode(); + } + return $result; + } + + public function fetch($method, &$result) + { + $ret = $this->parse($result); + $this->fetchParams($ret); + + switch ($method) + { + // normalize + case 'getList': + $ret['data'] = $ret['data']['item']; + break; + } + return $ret; + } + + /** + * New experimental XML parser, will be moved to XML handlers soon + * XXX replace xmlClass::xml2array() after this one passes all tests + * @param SimpleXmlIterator $xml + * @param string $parentName parent node name - used currently for debug only + * @return array|string + */ + public function parse($xml, $parentName = null) + { + $ret = array(); + $tags = array_keys(get_object_vars($xml)); + $count = $xml->count(); + $tcount = count($tags); + + if($count === 0) + { + $attr = (array) $xml->attributes(); + if(!empty($attr)) + { + $ret['@attributes'] = $attr['@attributes']; + $ret['@value'] = (string) $xml; + $ret['@value'] = trim($ret['@value']); + } + else + { + $ret = (string) $xml; + $ret = trim($ret); + } + return $ret; + } + + /** + * + * + * + * + */ + if($tcount === 1 && $count > 1) + { + foreach ($xml as $name => $node) + { + $_res = $this->parse($node, $name); + if(is_string($_res)) + { + $_res = trim($_res); + } + + $ret[$name][] = $this->parse($node, $name); + } + } + // default + else + { + foreach ($xml as $name => $node) + { + if(in_array($name, $this->_forceArray)) + { + $_res = $this->parse($node, $name); + if(is_string($_res)) $_res = trim($_res); + + if(empty($_res)) $ret[$name] = array(); // empty + elseif(is_string($_res)) $ret[$name][] = $_res; // string + else + { + if(in_array($name, $this->_forceNumericalArray)) $ret[$name][] = $_res; //array - controlled force numerical array + else $ret[$name] = $_res; //array, no force + } + } + else $ret[$name] = $this->parse($node, $name); + } + } + + + $attr = (array) $xml->attributes(); + if(!empty($attr)) + { + $ret['@attributes'] = $attr['@attributes']; + } + + return $ret; + } + + /** + * Normalize parameters/attributes + * @param array $result parsed to array XML response data + */ + public function fetchParams(&$result) + { + foreach ($result as $tag => $data) + { + if($tag === 'params') + { + foreach ($data['param'] as $i => $param) + { + $result[$tag][$param['@attributes']['name']] = $param['@value']; + unset($result[$tag]['param'][$i]); + } + unset($result[$tag]['param']); + } + elseif($tag === 'exception') + { + $result['exception'] = array('code' => (int) $result['exception']['@attributes']['code'], 'message' => $result['exception']['@value']); + //unset($result['exception']); + } + elseif($tag === '@attributes') + { + $result['params'] = $result['@attributes']; + unset($result['@attributes']); + } + elseif(is_array($result[$tag])) + { + $this->fetchParams($result[$tag]); + } + } + } + + /** + * @param string $method + * @param xmlClass $client + */ + public function prepareClient($method, &$client) + { + switch ($method) + { + case 'getList': + $this->_forceArray = array('item', 'screenshots', 'image'); + $this->_forceNumericalArray = array('item', 'image'); + //$client->setOptArrayTags('item,screenshots,image') + // ->setOptStringTags('icon,folder,version,author,authorURL,date,compatibility,url,thumbnail,featured,livedemo,price,name,description,category,image'); + break; + } + } + + /** + * @return xmlClass + */ + public function client() + { + return e107::getXml(false); + } +} + +class eAuth +{ + + /** + * e107.org manage client credentials (Consumer Key and Secret) URL + * @var string + */ + protected $eauthConsumerUrl = 'https://e107.org/eauth/client'; + + /** + * URL used to make temporary credential request (Request Token and Secret) to e107.org before the authorization phase + * @var string + */ + protected $eauthRequestUrl = 'https://e107.org/eauth/initialize'; + + /** + * URL used to redirect and authorize the resource owner (user) on e107.org using temporary (request) token + * @var string + */ + protected $eauthAuthorizeUrl = 'https://e107.org/eauth/authorize'; + + /** + * URL used to obtain token credentials (Access Token and Secret) from e107.org using temporary (request) token + * @var string + */ + protected $eauthAccessUrl = 'https://e107.org/eauth/token'; + + /** + * Public client key (generated and obtained from e107.org) + * @var string + */ + public $eauthConsumerKey = null; + + /** + * Client shared secret (generated and obtained from e107.org) + * @var string + */ + public $eauthConsumerSecret = null; + + /** + * Public temporary request token (generated and obtained from e107.org) + * @var string + */ + public $eauthRequestKey = null; + + /** + * Temporary request shared secret (generated and obtained from e107.org) + * @var string + */ + public $eauthRequestSecret = null; + + /** + * Public access token (generated and obtained from e107.org) + * @var string + */ + public $eauthAccessToken = null; + + /** + * Access shared secret (generated and obtained from e107.org) + * @var string + */ + public $eauthAccessSecret = null; + + /** + * Request method POST || GET + * @var string + */ + public $requestMethod = null; + + public function isClient() + { + $this->loadSysCredentials(); + return (!empty($this->eauthConsumerKey) && !empty($this->eauthConsumerSecret)); + } + + public function isInitialized() + { + $this->loadSysCredentials(); + return ($this->isClient() && !empty($this->eauthRequestKey) && !empty($this->eauthRequestSecret)); + } + + public function hasAccess() + { + $this->loadSysCredentials(); + return ($this->isClient() && !empty($this->eauthAccessToken) && !empty($this->eauthAccessSecret)); + } + + public function serviceAuthData($method, $args, $toObject = true) + { + // The client has previously registered with the server and obtained the client identifier dpf43f3p2l4k3l03 and client secret kd94hf93k423kf44. + // It has executed the eAuth workflow and obtained an access token nnch734d00sl2jdk and token secret pfkkdhi9sl3r4s00 + + $date = gmdate('Y-m-d H:i:s'); + $timestamp = $this->gmtTime($date); + $nonce = $this->nonce($timestamp); // create nonce + + $cryptMethod = $this->cryptMethod(); + $authData = array( + 'eauth_consumer_key' => $this->eauthConsumerKey, // (Client Identifier) Application key + 'eauth_token' => $this->eauthAccessToken, // Access Token + 'eauth_nonce' => $nonce,//'kllo9940pd9333jh' 'nonce' (number used once) string + 'eauth_timestamp' => $timestamp, // timestamp + 'eauth_signature_method'=> $cryptMethod, // encryption method + 'eauth_version' => '1.0', // signature method + ); + + // current request parameters + $args['action'] = $method; + + // signature data for building the signature + $signatureData = $authData; + + // add request parameters to the signature array + $signatureData['eauth_request_params'] = $args; + + // sort all + self::array_kmultisort($signatureData); + + // signature base string + $signatureBaseString = $this->requestMethod.'&'.rawurlencode($this->serviceUrl).'&'.http_build_query($signatureData, false, '&'); + $secretKey = rawurlencode($this->eauthConsumerSecret).'&'.rawurlencode($this->eauthAccessSecret); + + // crypt it + $signature = $this->crypt($signatureBaseString, $secretKey); + + //encode it + $authData['eauth_signature'] = base64_encode($signature); + if($toObject) return self::toObject($authData); + + return $authData; + } + + + public static function toObject($array) + { + $obj = new stdClass; + foreach ($array as $key => $value) + { + $obj->$key = $value; + } + return $obj; + } + + /** + * Load credentials stored in a system file + * @param boolean $force + * @return e_marketplace_adapter_abstract adapter instance + */ + public function loadSysCredentials($force = false) + { + if($force || null === $this->eauthConsumerKey) + { + $data = e107::getArrayStorage()->load('eauth'); + if(empty($data)) $data = array(); + $this->eauthConsumerKey = varset($data['consumer_key'], ''); + $this->eauthConsumerSecret = varset($data['consumer_secret'], ''); + $this->eauthAccessToken = varset($data['access_token'], ''); + $this->eauthAccessSecret = varset($data['access_secret'], ''); + } + return $this; + } + + public function storeSysCredentials($credentials = null) + { + if(null === $credentials) + { + $credentials = array( + 'consumer_key' => $this->eauthConsumerKey, + 'consumer_secret' => $this->eauthConsumerSecret, + 'access_token' => $this->eauthAccessToken, + 'access_secret' => $this->eauthAccessSecret, + ); + } + if(!is_array($credentials)) return false; + + foreach ($credentials as $key => $value) + { + switch ($key) + { + case 'consumer_key': + case 'consumer_secret': + case 'access_token': + case 'access_secret': + // OK + break; + + default: + unset($credentials[$key]); + break; + } + } + + return e107::getArrayStorage()->store($credentials, 'eauth'); + } + + /** + * Retrieve available system credentials or credential value + * @param string $key [optional] + * return mixed array of all credentials or string credential value + */ + public function getCredentials($key = null) + { + $this->loadSysCredentials(); + + $credentials = array( + 'consumer_key' => $this->eauthConsumerKey, + 'consumer_secret' => $this->eauthConsumerSecret, + 'access_token' => $this->eauthAccessToken, + 'access_secret' => $this->eauthAccessSecret, + ); + if(null !== $key) return varset($credentials[$key], null); + return $credentials; + } + + public function toAuthHeader($params) + { + $first = true; + $realm = isset($params['realm']) ? $params['realm'] : null; + if($realm) + { + $out = 'Authorization: eAuth realm="'.rawurlencode($realm).'"'; + $first = false; + } + else + $out = 'Authorization: eAuth'; + + $total = array(); + foreach($params as $k => $v) + { + if(substr($k, 0, 5) != "eauth") continue; + if(is_array($v)) + { + throw new Exception('Arrays not supported in headers', 200); + } + $out .= ($first) ? ' ' : ','; + $out .= rawurlencode($k).'="'.rawurlencode($v).'"'; + $first = false; + } + return $out; + } + + + public function cryptMethod() + { + return function_exists('hash_hmac') ? 'HMAC-SHA1' : 'SHA1'; + } + + function random($bits = 256) + { + $bytes = ceil($bits / 8); + $ret = ''; + for ($i = 0; $i < $bytes; $i++) + { + $ret .= chr(mt_rand(0, 255)); + } + return $ret; + } + + public function crypt($string, $secretKey) + { + $cMethod = $this->cryptMethod(); + // Append secret if it's sha1 + if($cMethod == 'SHA1') + { + return sha1($string.$secretKey); + } + // use secret key if HMAC-SHA1 + return hash_hmac('sha1', $string, $secretKey); + } + + public function nonce($timestamp) + { + return $this->crypt($this->random().$timestamp, $this->eauthAccessSecret.$this->eauthConsumerSecret); + } + + public function gmtTime($string) + { + $ret = false; + // mask - Y-m-d H:i:s + if(preg_match('#(.*?)-(.*?)-(.*?) (.*?):(.*?):(.*?)$#', $string, $matches)) + { + $ret = gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]); + } + return $ret; + } + + public static function array_kmultisort(&$array, $order = 'asc') + { + $func = $order == 'asc' ? 'ksort' : 'krsort'; + $func($array); + foreach ($array as $key => $value) + { + if(is_array($value)) + { + self::array_kmultisort($value, $order); + $array[$key] = $value; + } + } + } +} diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php index c0301fa0b..28f2c00d7 100644 --- a/e107_handlers/form_handler.php +++ b/e107_handlers/form_handler.php @@ -1,7665 +1,7665 @@ - (mixed) custom id attribute value - * if numeric value is passed it'll be just appended to the name e.g. {filed-name}-{value} - * if false is passed id will be not created - * if empty string is passed (or no 'id' option is found) - * in all other cases the value will be used as field id - * default: empty string - * - * - class => (string) field class(es) - * Example: 'tbox select class1 class2 class3' - * NOTE: this will override core classes, so you have to explicit include them! - * default: empty string - * - * - size => (int) size attribute value (used when needed) - * default: 40 - * - * - title (string) title attribute - * default: empty string (omitted) - * - * - readonly => (bool) readonly attribute - * default: false - * - * - selected => (bool) selected attribute (used when needed) - * default: false - * - * checked => (bool) checked attribute (used when needed) - * default: false - * - disabled => (bool) disabled attribute - * default: false - * - * - tabindex => (int) tabindex attribute value - * default: inner tabindex counter - * - * - other => (string) additional data - * Example: 'attribute1="value1" attribute2="value2"' - * default: empty string - */ -class e_form -{ - protected $_tabindex_counter = 0; - protected $_tabindex_enabled = true; - protected $_cached_attributes = array(); - protected $_field_warnings = array(); - private $_inline_token = null; - - /** - * @var user_class - */ - protected $_uc; - - protected $_required_string; - - function __construct($enable_tabindex = false) - { - e107_include_once(e_LANGUAGEDIR.e_LANGUAGE."/lan_form_handler.php"); - $this->_tabindex_enabled = $enable_tabindex; - $this->_uc = e107::getUserClass(); - $this->setRequiredString(' *'); - } - - /** - * @return array - * @see https://github.com/e107inc/e107/issues/3533 - */ - private static function sort_get_files_output($tmp) - { - usort($tmp, function ($left, $right) { - $left_full_path = $left['path'] . $left['fname']; - $right_full_path = $right['path'] . $right['fname']; - return strcmp($left_full_path, $right_full_path); - }); - return $tmp; - } - - - public function addWarning($field) - { - $this->_field_warnings[] = $field; - - } - - /** - * Open a new form - * @param string name - * @param $method - post|get default is post - * @param @target - e_REQUEST_URI by default - * @param $other - unused at the moment. - * @return string - */ - public function open($name, $method=null, $target=null, $options=null) - { - if($target == null) - { - $target = e_REQUEST_URI; - } - - if($method == null) - { - $method = "post"; - } - - $class = ""; - $autoComplete = ""; - - if(is_string($options)) - { - parse_str($options, $options); - } - - if(vartrue($options['class'])) - { - $class = "class='".$options['class']."'"; - } - else // default - { - $class= "class='form-horizontal'"; - } - - if(isset($options['autocomplete'])) // leave as isset() - { - $autoComplete = " autocomplete='".($options['autocomplete'] ? 'on' : 'off')."'"; - } - - - if($method == 'get' && strpos($target,'=')) - { - list($url,$qry) = explode("?",$target); - $text = "\n
\n"; - - parse_str($qry,$m); - foreach($m as $k=>$v) - { - $text .= $this->hidden($k, $v); - } - - } - else - { - $target = str_replace("&", "&", $target); - $text = "\n\n"; - } - return $text; - } - - /** - * Close a Form - */ - public function close() - { - return "
"; - - } - - - /** - * Render a country drop-down list. - * @param string $name - * @param string $value - * @param array $options - * @return string - */ - public function country($name, $value, $options=array()) - { - - $arr = $this->getCountry(); - - $placeholder = isset($options['placeholder']) ? $options['placeholder'] : ' '; - - return $this->select($name, $arr, $value, $options, $placeholder); - } - - - /** - * Get a list of countries. - * @param null|string $iso ISO code. - * @return array|mixed|string - */ - public function getCountry($iso=null) // move to parser? - { - - $c = array(); - - $c['af'] = "Afghanistan"; - $c['al'] = "Albania"; - $c['dz'] = "Algeria"; - $c['as'] = "American Samoa"; - $c['ad'] = "Andorra"; - $c['ao'] = "Angola"; - $c['ai'] = "Anguilla"; - $c['aq'] = "Antarctica"; - $c['ag'] = "Antigua and Barbuda"; - $c['ar'] = "Argentina"; - $c['am'] = "Armenia"; - $c['aw'] = "Aruba"; - $c['au'] = "Australia"; - $c['at'] = "Austria"; - $c['az'] = "Azerbaijan"; - $c['bs'] = "Bahamas"; - $c['bh'] = "Bahrain"; - $c['bd'] = "Bangladesh"; - $c['bb'] = "Barbados"; - $c['by'] = "Belarus"; - $c['be'] = "Belgium"; - $c['bz'] = "Belize"; - $c['bj'] = "Benin"; - $c['bm'] = "Bermuda"; - $c['bt'] = "Bhutan"; - $c['bo'] = "Bolivia"; - $c['ba'] = "Bosnia-Herzegovina"; - $c['bw'] = "Botswana"; - $c['bv'] = "Bouvet Island"; - $c['br'] = "Brazil"; - $c['io'] = "British Indian Ocean Territory"; - $c['bn'] = "Brunei Darussalam"; - $c['bg'] = "Bulgaria"; - $c['bf'] = "Burkina Faso"; - $c['bi'] = "Burundi"; - $c['kh'] = "Cambodia"; - $c['cm'] = "Cameroon"; - $c['ca'] = "Canada"; - - $c['cv'] = "Cape Verde"; - $c['ky'] = "Cayman Islands"; - $c['cf'] = "Central African Republic"; - $c['td'] = "Chad"; - $c['cl'] = "Chile"; - $c['cn'] = "China"; - $c['cx'] = "Christmas Island"; - $c['cc'] = "Cocos (Keeling) Islands"; - $c['co'] = "Colombia"; - $c['km'] = "Comoros"; - $c['cg'] = "Congo"; - $c['cd'] = "Congo (Dem.Rep)"; - $c['ck'] = "Cook Islands"; - $c['cr'] = "Costa Rica"; - $c['hr'] = "Croatia"; - $c['cu'] = "Cuba"; - $c['cy'] = "Cyprus"; - $c['cz'] = "Czech Republic"; - $c['dk'] = "Denmark"; - $c['dj'] = "Djibouti"; - $c['dm'] = "Dominica"; - $c['do'] = "Dominican Republic"; - $c['tp'] = "East Timor"; - $c['ec'] = "Ecuador"; - $c['eg'] = "Egypt"; - $c['sv'] = "El Salvador"; - $c['gq'] = "Equatorial Guinea"; - $c['er'] = "Eritrea"; - $c['ee'] = "Estonia"; - $c['et'] = "Ethiopia"; - $c['fk'] = "Falkland Islands"; - $c['fo'] = "Faroe Islands"; - $c['fj'] = "Fiji"; - $c['fi'] = "Finland"; - // $c['cs'] = "Former Czechoslovakia"; - // $c['su'] = "Former USSR"; - $c['fr'] = "France"; - // $c['fx'] = "France (European Territory)"; - $c['gf'] = "French Guyana"; - $c['tf'] = "French Southern Territories"; - $c['ga'] = "Gabon"; - $c['gm'] = "Gambia"; - $c['ge'] = "Georgia"; - $c['de'] = "Germany"; - $c['gh'] = "Ghana"; - $c['gi'] = "Gibraltar"; - $c['gr'] = "Greece"; - $c['gl'] = "Greenland"; - $c['gd'] = "Grenada"; - $c['gp'] = "Guadeloupe (French)"; - $c['gu'] = "Guam (USA)"; - $c['gt'] = "Guatemala"; - $c['gn'] = "Guinea"; - $c['gw'] = "Guinea Bissau"; - $c['gy'] = "Guyana"; - $c['ht'] = "Haiti"; - $c['hm'] = "Heard and McDonald Islands"; - $c['hn'] = "Honduras"; - $c['hk'] = "Hong Kong"; - $c['hu'] = "Hungary"; - $c['is'] = "Iceland"; - $c['in'] = "India"; - $c['id'] = "Indonesia"; - $c['ir'] = "Iran"; - $c['iq'] = "Iraq"; - $c['ie'] = "Ireland"; - $c['il'] = "Israel"; - $c['it'] = "Italy"; - $c['ci'] = "Ivory Coast (Cote D'Ivoire)"; - $c['jm'] = "Jamaica"; - $c['jp'] = "Japan"; - $c['jo'] = "Jordan"; - $c['kz'] = "Kazakhstan"; - $c['ke'] = "Kenya"; - $c['ki'] = "Kiribati"; - $c['kp'] = "Korea (North)"; - $c['kr'] = "Korea (South)"; - $c['kw'] = "Kuwait"; - $c['kg'] = "Kyrgyzstan"; - $c['la'] = "Laos"; - $c['lv'] = "Latvia"; - $c['lb'] = "Lebanon"; - $c['ls'] = "Lesotho"; - $c['lr'] = "Liberia"; - $c['ly'] = "Libya"; - $c['li'] = "Liechtenstein"; - $c['lt'] = "Lithuania"; - $c['lu'] = "Luxembourg"; - $c['mo'] = "Macau"; - $c['mk'] = "Macedonia"; - $c['mg'] = "Madagascar"; - $c['mw'] = "Malawi"; - $c['my'] = "Malaysia"; - $c['mv'] = "Maldives"; - $c['ml'] = "Mali"; - $c['mt'] = "Malta"; - $c['mh'] = "Marshall Islands"; - $c['mq'] = "Martinique (French)"; - $c['mr'] = "Mauritania"; - $c['mu'] = "Mauritius"; - $c['yt'] = "Mayotte"; - $c['mx'] = "Mexico"; - $c['fm'] = "Micronesia"; - $c['md'] = "Moldavia"; - $c['mc'] = "Monaco"; - $c['mn'] = "Mongolia"; - $c['me'] = "Montenegro"; - $c['ms'] = "Montserrat"; - $c['ma'] = "Morocco"; - $c['mz'] = "Mozambique"; - $c['mm'] = "Myanmar"; - $c['na'] = "Namibia"; - $c['nr'] = "Nauru"; - $c['np'] = "Nepal"; - $c['nl'] = "Netherlands"; - $c['an'] = "Netherlands Antilles"; - // $c['net'] = "Network"; - - $c['nc'] = "New Caledonia (French)"; - $c['nz'] = "New Zealand"; - $c['ni'] = "Nicaragua"; - $c['ne'] = "Niger"; - $c['ng'] = "Nigeria"; - $c['nu'] = "Niue"; - $c['nf'] = "Norfolk Island"; - - $c['mp'] = "Northern Mariana Islands"; - $c['no'] = "Norway"; - // $c['arpa'] = "Old style Arpanet"; - $c['om'] = "Oman"; - $c['pk'] = "Pakistan"; - $c['pw'] = "Palau"; - $c['pa'] = "Panama"; - $c['pg'] = "Papua New Guinea"; - $c['py'] = "Paraguay"; - $c['pe'] = "Peru"; - $c['ph'] = "Philippines"; - $c['pn'] = "Pitcairn Island"; - $c['pl'] = "Poland"; - $c['pf'] = "Polynesia (French)"; - $c['pt'] = "Portugal"; - $c['pr'] = "Puerto Rico"; - $c['ps'] = "Palestine"; - $c['qa'] = "Qatar"; - $c['re'] = "Reunion (French)"; - $c['ro'] = "Romania"; - $c['ru'] = "Russia"; - $c['rw'] = "Rwanda"; - $c['gs'] = "S. Georgia & S. Sandwich Isls."; - $c['sh'] = "Saint Helena"; - $c['kn'] = "Saint Kitts & Nevis"; - $c['lc'] = "Saint Lucia"; - $c['pm'] = "Saint Pierre and Miquelon"; - $c['st'] = "Saint Tome (Sao Tome) and Principe"; - $c['vc'] = "Saint Vincent & Grenadines"; - $c['ws'] = "Samoa"; - $c['sm'] = "San Marino"; - $c['sa'] = "Saudi Arabia"; - $c['sn'] = "Senegal"; - $c['rs'] = "Serbia"; - $c['sc'] = "Seychelles"; - $c['sl'] = "Sierra Leone"; - $c['sg'] = "Singapore"; - $c['sk'] = "Slovak Republic"; - $c['si'] = "Slovenia"; - $c['sb'] = "Solomon Islands"; - $c['so'] = "Somalia"; - $c['za'] = "South Africa"; - - $c['es'] = "Spain"; - $c['lk'] = "Sri Lanka"; - $c['sd'] = "Sudan"; - $c['sr'] = "Suriname"; - $c['sj'] = "Svalbard and Jan Mayen Islands"; - $c['sz'] = "Swaziland"; - $c['se'] = "Sweden"; - $c['ch'] = "Switzerland"; - $c['sy'] = "Syria"; - $c['tj'] = "Tadjikistan"; - $c['tw'] = "Taiwan"; - $c['tz'] = "Tanzania"; - $c['th'] = "Thailand"; - $c['ti'] = "Tibet"; - $c['tg'] = "Togo"; - $c['tk'] = "Tokelau"; - $c['to'] = "Tonga"; - $c['tt'] = "Trinidad and Tobago"; - $c['tn'] = "Tunisia"; - $c['tr'] = "Turkey"; - $c['tm'] = "Turkmenistan"; - $c['tc'] = "Turks and Caicos Islands"; - $c['tv'] = "Tuvalu"; - $c['ug'] = "Uganda"; - $c['ua'] = "Ukraine"; - $c['ae'] = "United Arab Emirates"; - $c['gb'] = "United Kingdom"; - $c['us'] = "United States"; - $c['uy'] = "Uruguay"; - $c['um'] = "US Minor Outlying Islands"; - $c['uz'] = "Uzbekistan"; - $c['vu'] = "Vanuatu"; - $c['va'] = "Vatican City State"; - $c['ve'] = "Venezuela"; - $c['vn'] = "Vietnam"; - $c['vg'] = "Virgin Islands (British)"; - $c['vi'] = "Virgin Islands (USA)"; - $c['wf'] = "Wallis and Futuna Islands"; - $c['eh'] = "Western Sahara"; - $c['ye'] = "Yemen"; - - // $c['zr'] = "(deprecated) Zaire"; - $c['zm'] = "Zambia"; - $c['zw'] = "Zimbabwe"; - - - if(!empty($iso) && !empty($c[$iso])) - { - return $c[$iso]; - } - - - return ($iso === null) ? $c : ''; - - } - - - /** - * Get required field markup string - * @return string - */ - public function getRequiredString() - { - return $this->_required_string; - } - - /** - * Set required field markup string - * @param string $string - * @return e_form - */ - public function setRequiredString($string) - { - $this->_required_string = $string; - return $this; - } - - // For Comma separated keyword tags. - function tags($name, $value, $maxlength = 200, $options = array()) - { - if(is_string($options)) parse_str($options, $options); - - $defaults['selectize'] = array( - 'create' => true, - 'maxItems' => vartrue($options['maxItems'], 7), - 'mode' => 'multi', - 'plugins' => array('remove_button'), - ); - - $options = array_replace_recursive($defaults, $options); - - return $this->text($name, $value, $maxlength, $options); - } - - - - - - - /** - * Render Bootstrap Tabs - * @param $array - * @param $options - * @example - * $array = array( - * 'home' => array('caption' => 'Home', 'text' => 'some tab content' ), - * 'other' => array('caption' => 'Other', 'text' => 'second tab content' ) - * ); - */ - function tabs($array,$options = array()) - { - $initTab = varset($options['active'],false); - $id = !empty($options['id']) ? 'id="'.$options['id'].'"' : ''; - $text =' - - '; - - $initTab = varset($options['active'],false); - $tabClass = varset($options['class'],null); - - $text .= ' - -
'; - - $c=0; - foreach($array as $key=>$tab) - { - - - if(is_numeric($key)) - { - $key = 'tab-'.$key; - } - - if($c == 0 & $initTab == false) - { - $initTab = $key; - } - - $active = ($key == $initTab) ? ' active' : ''; - $text .= '
'.$tab['text'].'
'; - $c++; - } - - $text .= ' -
'; - - return $text; - - } - - - /** - * Render Bootstrap Carousel - * @param string $name : A unique name - * @param array $array - * @param array $options : default, interval, pause, wrap - * @return string|array - * @example - * $array = array( - * 'slide1' => array('caption' => 'Slide 1', 'text' => 'first slide content' ), - * 'slide2' => array('caption' => 'Slide 2', 'text' => 'second slide content' ), - * 'slide3' => array('caption' => 'Slide 3', 'text' => 'third slide content' ) - * ); - */ - function carousel($name="e-carousel", $array, $options = null) - { - $interval = null; - $wrap = null; - $pause = null; - $indicators = ''; - $controls = ''; - - $act = varset($options['default'], 0); - - if(isset($options['wrap'])) - { - $wrap = 'data-wrap="'.$options['wrap'].'"'; - } - - if(isset($options['interval'])) - { - $interval = 'data-interval="'.$options['interval'].'"'; - } - - if(isset($options['pause'])) - { - $pause = 'data-pause="'.$options['pause'].'"'; - } - - - $start =' - - - '; - - if(!empty($options['data'])) - { - return array( - 'start' => $start, - 'indicators' => $indicators, - 'inner' => $inner, - 'controls' => $controls, - 'end' => $end - ); - } - - return $start.$indicators.$inner.$controls.$end; // $text; - - } - - /** - * Same as $this->text() except it adds input validation for urls. - * At this stage, checking only for spaces. Should include sef-urls. - */ - function url($name, $value = '', $maxlength = 80, $options= array()) - { - $options['pattern'] = '^\S*$'; - return $this->text($name, $value, $maxlength, $options); - } - - /** - * Text-Field Form Element - * @param $name - * @param $value - * @param $maxlength - * @param $options - * - size: mini, small, medium, large, xlarge, xxlarge - * - class: - * - typeahead: 'users' - * - * @return string - */ - function text($name, $value = '', $maxlength = 80, $options= array()) - { - if(is_string($options)) - { - parse_str($options,$options); - } - - if(!vartrue($options['class'])) - { - $options['class'] = "tbox"; - } - - if(deftrue('BOOTSTRAP')) - { - $options['class'] .= ' form-control'; - } - - /* - if(!vartrue($options['class'])) - { - if($maxlength < 10) - { - $options['class'] = 'tbox input-text span3'; - } - - elseif($maxlength < 50) - { - $options['class'] = 'tbox input-text span7'; - } - - elseif($maxlength > 99) - { - $options['class'] = 'tbox input-text span7'; - } - else - { - $options['class'] = 'tbox input-text'; - } - } - */ - - if(!empty($options['selectize'])) - { - e107::js('core', 'selectize/js/selectize.min.js', 'jquery'); - e107::css('core', 'selectize/css/selectize.css', 'jquery'); - - if(deftrue('BOOTSTRAP') === 3) - { - // e107::css('core', 'selectize/css/selectize.bootstrap3.css', 'jquery'); - } - elseif(deftrue('BOOTSTRAP')) - { - // e107::css('core', 'selectize/css/selectize.bootstrap2.css', 'jquery'); - } - - // Load selectize behavior. - e107::js('core', 'selectize/js/selectize.init.js', 'jquery'); - - $options['selectize']['wrapperClass'] = 'selectize-control'; - $options['selectize']['inputClass'] = 'form-control selectize-input '; - $options['selectize']['dropdownClass'] = 'selectize-dropdown'; - $options['selectize']['dropdownContentClass'] = 'selectize-dropdown-content'; - $options['selectize']['copyClassesToDropdown'] = true; - - $jsSettings = array( - 'id' => vartrue($options['id'], $this->name2id($name)), - 'options' => $options['selectize'], - // Multilingual support. - 'strings' => array( - 'anonymous' => LAN_ANONYMOUS, - ), - ); - - // Merge field settings with other selectize field settings. - e107::js('settings', array('selectize' => array($jsSettings))); - - $options['class'] = ''; - } - - // TODO: remove typeahead. - if(vartrue($options['typeahead'])) - { - if(vartrue($options['typeahead']) == 'users') - { - $options['data-source'] = e_BASE."user.php"; - $options['class'] .= " e-typeahead"; - } - } - - if(vartrue($options['size']) && !is_numeric($options['size'])) - { - $options['class'] .= " input-".$options['size']; - unset($options['size']); // don't include in html 'size='. - } - - $mlength = vartrue($maxlength) ? "maxlength=".$maxlength : ""; - - $type = varset($options['type']) == 'email' ? 'email' : 'text'; // used by $this->email(); - - $options = $this->format_options('text', $name, $options); - - - //never allow id in format name-value for text fields - return "get_attributes($options, $name)." />"; - } - - - /** - * Create a input [type number] - * - * Additional options: - * - decimals: default 0; defines the number of decimals allowed in this field (0 = only integers; 1 = integers & floats with 1 decimal e.g. 4.1, etc.) - * - step: default 1; defines the step for the spinner and the max. number of decimals. If decimals is given, step will be ignored - * - min: default 0; minimum value allowed - * - max: default empty; maximum value allowed - * - pattern: default empty; allows to define an complex input pattern - * - * @param string $name - * @param integer $value - * @param integer $maxlength - * @param array $options decimals, step, min, max, pattern - * @return string - */ - function number($name, $value=0, $maxlength = 200, $options = array()) - { - if(is_string($options)) parse_str($options, $options); - - if(!empty($options['maxlength'])) - { - $maxlength = $options['maxlength']; - } - - unset($options['maxlength']); - - if(empty($options['size'])) - { - $options['size'] = 15; - } - if(empty($options['class'])) - { - $options['class'] = 'tbox number e-spinner input-small '; - } - - if(!empty($options['size'])) - { - $options['class'] .= ' input-'.$options['size']; - unset($options['size']); - } - - $options['class'] .= " form-control"; - $options['type'] ='number'; - - // Not used anymore - //$mlength = vartrue($maxlength) ? "maxlength=".$maxlength : ""; - - // Always define the min. parameter - // defaults to 0 - // setting the min option to a negative value allows negative inputs - $min = " min='".varsettrue($options['min'], '0')."'"; - $max = isset($options['max']) ? " max='".$options['max']."'" : ''; - - if (!empty($options['pattern'])) - { - $pattern = ' pattern="'.trim($options['pattern']).'"'; - } - else - { - $options['pattern'] = '^'; - // ^\-?[0-9]*\.?[0-9]{0,2} - if (varset($options['min'], 0) < 0) - { - $options['pattern'] .= '\-?'; - } - $options['pattern'] .= '[0-9]*'; - - // Integer & Floaat/Double value handling - if (isset($options['decimals'])) - { - if (intval($options['decimals']) > 0) - { - $options['pattern'] .= '\.?[0-9]{0,'.intval($options['decimals']).'}'; - } - - // defined the step based on number of decimals - // 2 = 0.01 > allows integers and float numbers with up to 2 decimals (3.1 = OK; 3.12 = OK; 3.123 = NOK) - // 1 = 0.1 > allows integers and float numbers with up to 2 decimals (3.1 = OK; 3.12 = NOK) - // 0 = 1 > allows only integers, no float values - if (intval($options['decimals']) <= 0) - { - $step = "step='1'"; - } - else - { - $step = "step='0." . str_pad(1, intval($options['decimals']), 0, STR_PAD_LEFT) . "'"; - } - } - else - { - // decimal option not defined - // check for step option (1, 0.1, 0.01, and so on) - // or set default step 1 (integers only) - $step = "step='" . varsettrue($options['step'], '1') . "'"; - } - - $pattern = ' pattern="'.$options['pattern'].'"'; - } - $options = $this->format_options('text', $name, $options); - - //never allow id in format name-value for text fields - if(THEME_LEGACY === false) - { - // return "get_attributes($options, $name)." />"; - return "get_attributes($options, $name)." />"; - } - - return $this->text($name, $value, $maxlength, $options); - } - - - - function email($name, $value, $maxlength = 200, $options = array()) - { - $options['type'] = 'email'; - return $this->text($name,$value,$maxlength,$options); - } - - - - function iconpreview($id, $default, $width='', $height='') // FIXME - { - // XXX - $name ?! - // $parms = $name."|".$width."|".$height."|".$id; - $sc_parameters = 'mode=preview&default='.$default.'&id='.$id; - return e107::getParser()->parseTemplate("{ICONPICKER=".$sc_parameters."}"); - } - - /** - * @param $name - * @param $default value - * @param $label - * @param $options - gylphs=1 - * @param $ajax - */ - function iconpicker($name, $default, $label, $options = array(), $ajax = true) - { - //v2.2.0 - $options['icon'] = 1; - $options['glyph'] = 1; - $options['w'] = 64; - $options['h'] = 64; - $options['media'] = '_icon'; - - if(!isset($options['legacyPath'])) - { - $options['legacyPath'] = "{e_IMAGE}icons"; - } - - return $this->mediapicker($name, $default, $options); - - - /* $options['media'] = '_icon'; - $options['legacyPath'] = "{e_IMAGE}icons"; - - return $this->imagepicker($name, $default, $label, $options);*/ - - - } - - - /** - * Internal Function used by imagepicker, filepicker, mediapicker() - * @param string $category - * @param string $label - * @param string $tagid - * @param null $extras - * @return string - */ - public function mediaUrl($category = '', $label = '', $tagid='', $extras=null) - { - if(is_string($extras)) - { - parse_str($extras,$extras); - } - - $category = str_replace('+', '^', $category); // Bc Fix. - - $cat = ($category) ? '&for='.urlencode($category) : ""; - $mode = vartrue($extras['mode'],'main'); - $action = vartrue($extras['action'],'dialog'); - - - - if(empty($label)) - { - $label = ' Upload an image or file'; - } - - // TODO - option to choose which tabs to display by default. - - $url = e_ADMIN_ABS."image.php?mode={$mode}&action={$action}".$cat; - - if(!empty($tagid)) - { - $url .= '&tagid='.$tagid; - } - - if(!empty($extras['bbcode'])) - { - $url .= '&bbcode='.$extras['bbcode']; - } - - $url .= "&iframe=1"; - - if(vartrue($extras['w'])) - { - $url .= "&w=".$extras['w']; - } - - if(!empty($extras['image'])) - { - $url .= "&image=1"; - } - - if(!empty($extras['glyphs']) || !empty($extras['glyph'])) - { - $url .= "&glyph=1"; - } - - if(!empty($extras['icons']) || !empty($extras['icon'])) - { - $url .= "&icon=1"; - } - - if(!empty($extras['youtube'])) - { - $url .= "&youtube=1"; - } - - if(!empty($extras['video'])) - { - $url .= ($extras['video'] == 2) ? "&video=2" : "&video=1"; - } - - if(!empty($extras['audio'])) - { - $url .= "&audio=1"; - } - - if(!empty($extras['path']) && $extras['path'] == 'plugin') - { - $url .= "&path=".deftrue('e_CURRENT_PLUGIN'); - } - - if(E107_DBG_BASIC) - { - - $title = "Media Manager : ".$category; - } - else - { - $title = LAN_EDIT; - } - - $class = !empty($extras['class']) ? $extras['class']." " : ''; - $title = !empty($extras['title']) ? $extras['title'] : $title; - - $ret = "".$label.""; // using bootstrap. - - if(!e107::getRegistry('core/form/mediaurl')) - { - e107::setRegistry('core/form/mediaurl', true); - } - - return $ret; - } - - - /** - * Avatar Picker - * @param $name - form element name ie. value to be posted. - * @param $curVal - current avatar value. ie. the image-file name or URL. - */ - function avatarpicker($name,$curVal='',$options=array()) - { - - $tp = e107::getParser(); - $pref = e107::getPref(); - - $attr = "aw=".$pref['im_width']."&ah=".$pref['im_height']; - $tp->setThumbSize($pref['im_width'],$pref['im_height']); - - $blankImg = $tp->thumbUrl(e_IMAGE."generic/blank_avatar.jpg",$attr); - $localonly = true; //TODO add a pref for allowing external or internal avatars or both. - $idinput = $this->name2id($name); - $previnput = $idinput."-preview"; - $optioni = $idinput."-options"; - - - $path = (substr($curVal,0,8) == '-upload-') ? '{e_AVATAR}upload/' : '{e_AVATAR}default/'; - $newVal = str_replace('-upload-','',$curVal); - - $img = (strpos($curVal,"://")!==false) ? $curVal : $tp->thumbUrl($path.$newVal); - - if(!$curVal) - { - $img = $blankImg; - } - - $parm = $options; - $classlocal = (!empty($parm['class'])) ? "class='".$parm['class']." e-expandit e-tip avatar'" : " class='img-rounded rounded e-expandit e-tip avatar "; - $class = (!empty($parm['class'])) ? "class='".$parm['class']." e-expandit '" : " class='img-rounded rounded btn btn-default btn-secondary button e-expandit "; - - if($localonly == true) - { - $text = ""; - $text .= "".LAN_EFORM_001.""; - } - else - { - $text = ""; - $text .= ""; - $text .= ""; - } - - $avFiles = e107::getFile()->get_files(e_AVATAR_DEFAULT,".jpg|.png|.gif|.jpeg|.JPG|.GIF|.PNG"); - - $text .= "\n"; - - // Used by usersettings.php right now. - - - - - - - - return $text; - /* - //TODO discuss and FIXME - // Intentionally disable uploadable avatar and photos at this stage - if (false && $pref['avatar_upload'] && FILE_UPLOADS) - { - $text .= "
".LAN_SIGNUP_25." -
".LAN_SIGNUP_34."
"; - } - - if (false && $pref['photo_upload'] && FILE_UPLOADS) - { - $text .= "
".LAN_SIGNUP_26." -
".LAN_SIGNUP_34."
"; - } */ - } - - - - - /** - * Image Picker - - * @param string $name input name - * @param string $default default value - * @param string $label custom label - * @param string $sc_parameters shortcode parameters - * --- SC Parameter list --- - * - media: if present - load from media category table - * - w: preview width in pixels - * - h: preview height in pixels - * - help: tooltip - * - video: when set to true, will enable the Youtube (video) tab. - * @example $frm->imagepicker('banner_image', $_POST['banner_image'], '', 'banner'); // all images from category 'banner_image' + common images. - * @example $frm->imagepicker('banner_image', $_POST['banner_image'], '', 'media=banner&w=600'); - * @return string html output - */ - function imagepicker($name, $default, $previewURL = '', $sc_parameters = '') - { - - $tp = e107::getParser(); - $name_id = $this->name2id($name); - $meta_id = $name_id."-meta"; - - if(is_string($sc_parameters)) - { - if(strpos($sc_parameters, '=') === false) $sc_parameters = 'media='.$sc_parameters; - parse_str($sc_parameters, $sc_parameters); - } - elseif(empty($sc_parameters)) - { - $sc_parameters = array(); - } - - $cat = $tp->toDB(vartrue($sc_parameters['media'])); - - // if(deftrue('e_DEBUG_MEDIAPICKER')) - // { - // v2.2.0 - $sc_parameters['image'] = 1; - $sc_parameters['dropzone'] = 1; - if(!empty($sc_parameters['video'])) // bc fix - { - $sc_parameters['youtube'] = 1; - } - - return $this->mediapicker($name, $default, $sc_parameters); - // } - - - if(empty($sc_parameters['media'])) - { - $sc_parameters['media'] = '_common'; - } - - -// e107::getDebug()->log($sc_parameters); - - $default_thumb = $default; - $class = ''; - - if($default) - { - if($video = $tp->toVideo($default, array('thumb'=>'src'))) - { - $default_url = $video; - $class = 'image-selector-video'; - - } - else - { - if('{' != $default[0]) // legacy path or one without {} - { - list($default_thumb,$default) = $this->imagepickerDefault($default, $sc_parameters); - } - - $default_url = $tp->replaceConstants($default, 'abs'); - } - - - $debugInfo = " -
-			default-thumb: ".$default_thumb."
-			defautlt:   ".$default."
-			default-url: ".$default_url."
-			
"; - - // e107::getDebug()->log($debugInfo); - - - $blank = FALSE; - - - } - else - { - //$default = $default_url = e_IMAGE_ABS."generic/blank.gif"; - $default_url = e_IMAGE_ABS."generic/nomedia.png"; - $blank = TRUE; - $class = 'image-selector-empty'; - } - - - //$width = intval(vartrue($sc_parameters['width'], 150)); - - - if($cat == '_icon') // ICONS - { - $ret = "
"; - $thpath = isset($sc_parameters['nothumb']) || vartrue($hide) ? $default : $default_thumb; - - $label = "
"; - $label .= $tp->toIcon($default_url,array('class'=>'img-responsive img-fluid')); - - //$label = "
"; - //$label .= $tp->toIcon($default_url); - - $label .= "
"; - - // $label = "{$default_url}"; - - - $ret = $this->mediaUrl($cat, $label, $name_id, $sc_parameters); - } - else // Images - { - - $title = (vartrue($sc_parameters['help'])) ? "title='".$sc_parameters['help']."'" : ""; - $width = vartrue($sc_parameters['w'], 120); - $height = vartrue($sc_parameters['h'], 0); - - $ret = "
"; - $att = 'aw='.$width."'&ah=".$height."'"; - $thpath = empty($default) || !empty($video) ? $default_url : $tp->thumbUrl($default_thumb, $att, true); - //isset($sc_parameters['nothumb']) || vartrue($hide) ? - - $label = "{$default_url}"; - - if($cat != 'news' && $cat !='page' && $cat !='' && strpos($cat,'_image')===false) - { - $cat = $cat . "_image"; - } - - $sc_parameters['class'] = 'btn btn-sm btn-default'; - - if($blank === true) - { - $sc_parameters['title'] = LAN_ADD; - $editIcon = $this->mediaUrl($cat, $tp->toGlyph('fa-plus', array('fw'=>1)), $name_id,$sc_parameters); - $previewIcon = ''; - - // @todo drag-n-drop upload code in here. - } - else - { - $editIcon = $this->mediaUrl($cat, $tp->toGlyph('fa-edit', array('fw'=>1)), $name_id,$sc_parameters); - $previewIcon = "".$tp->toGlyph('fa-search', array('fw'=>1)).""; - } - - $ret .= $label; // image - - $ret .= '
-
'.$editIcon.$previewIcon.'
-
'; - } - - - $ret .= "
\n"; - $ret .= ""; - $ret .= ""; - - return $ret; - - } - - -/** - * Media Picker - - * @param string $name input name - * @param string $default default value - * @param string $parms shortcode parameters - * --- $parms list --- - * - media: if present - load from media category table - * - w: preview width in pixels - * - h: preview height in pixels - * - help: tooltip - * - youtube=1 (Enables the Youtube tab) - * - image=1 (Enable the Images tab) - * - video=1 (Enable the Video tab) - * - audio=1 (Enable the Audio tab) - * - glyph=1 (Enable the Glyphs tab). - * @example $frm->imagepicker('banner_image', $_POST['banner_image'], '', 'media=banner&w=600'); - * @return string html output - */ - function mediapicker($name, $default, $parms = '') - { - - - $tp = e107::getParser(); - $name_id = $this->name2id($name); - $meta_id = $name_id."-meta"; - - if(is_string($parms)) - { - if(strpos($parms, '=') === false) $parms = 'media='.$parms; - parse_str($parms, $parms); - } - elseif(empty($parms)) - { - $parms = array(); - } - - - if(empty($parms['media'])) - { - $parms['media'] = '_common'; - } - - $title = !empty($parms['help']) ? "title='".$parms['help']."'" : ""; - - if(!isset($parms['w'])) - { - $parms['w'] = 220; - } - - if(!isset($parms['h'])) - { - $parms['h'] = 190; - } - - - // $width = vartrue($parms['w'], 220); - // $height = vartrue($parms['h'], 190); - // e107::getDebug()->log($parms); - - // Test Files... - // $default = '{e_MEDIA_VIDEO}2018-07/samplevideo_720x480_2mb.mp4'; - // $default = '{e_MEDIA_FILE}2016-03/Colony_Harry_Gregson_Williams.mp3'; - // $default = '{e_PLUGIN}gallery/images/butterfly.jpg'; - // $default = 'NuIAYHVeFYs.youtube'; - // $default = ''; // empty - // $default = '{e_MEDIA_IMAGE}2018-07/Jellyfish.jpg'; - - $class = ''; - - if($parms['icon']) - { - $class = 'icon-preview mediaselector-container-icon'; - $parms['type'] = 'icon'; - } - - $preview = e107::getMedia()->previewTag($default,$parms); - - $cat = $tp->toDB(vartrue($parms['media'])); - - $ret = "
"; - - $parms['class'] = 'btn btn-sm btn-default'; - - $dropzone = !empty($parms['dropzone']) ? " dropzone" : ""; - // $parms['modal-delete-label'] = LAN_DELETE; - - if(empty($preview)) - { - $parms['title'] = LAN_ADD; - $editIcon = $this->mediaUrl($cat, $tp->toGlyph('fa-plus', array('fw'=>1)), $name_id,$parms); - $previewIcon = ''; - } - else - { - $editIcon = $this->mediaUrl($cat, $tp->toGlyph('fa-edit', array('fw'=>1)), $name_id,$parms); - // $previewIcon = "".$tp->toGlyph('fa-search', array('fw'=>1)).""; - $previewIcon = ''; - } - - - if(!empty($parms['icon'])) // empty overlay without button. - { - $parms['class'] = ''; - $editIcon = $this->mediaUrl($cat, "", $name_id,$parms); - } - - $ret .= "
"; - - $ret .= $preview; // image, video. audio tag etc. - - $ret .= '
-
'.$editIcon.$previewIcon.'
-
'; - - $ret .= "
\n"; - $ret .= ""; - $ret .= ""; - - if(empty($dropzone)) - { - return $ret; - } - // Drag-n-Drop Upload - // @see https://www.dropzonejs.com/#server-side-implementation - - e107::js('footer', e_WEB_ABS."lib/dropzone/dropzone.min.js"); - e107::css('url', e_WEB_ABS."lib/dropzone/dropzone.min.css"); - e107::css('inline', " - .dropzone { background: transparent; border:0 } - "); - - $INLINEJS = " - Dropzone.autoDiscover = false; - $(function() { - $('#".$name_id."_prev').dropzone({ - url: '".e_JS."plupload/upload.php?for=".$cat."', - createImageThumbnails: false, - uploadMultiple :false, - dictDefaultMessage: \"".defset('LAN_UI_DROPZONE_DROP_FILES', "Drop files here to upload")."\", - maxFilesize: ".(int) ini_get('upload_max_filesize').", - success: function (file, response) { - - file.previewElement.classList.add('dz-success'); - - // console.log(response); - - if(response) - { - var decoded = jQuery.parseJSON(response); - console.log(decoded); - if(decoded.preview && decoded.result) - { - $('#".$name_id."').val(decoded.result); - $('#".$name_id."_prev').html(decoded.preview); - } - else if(decoded.error) - { - file.previewElement.classList.add('dz-error'); - $('#".$name_id."_prev').html(decoded.error.message); - } - } - - }, - error: function (file, response) { - file.previewElement.classList.add('dz-error'); - } - }); - }); - - "; - - - e107::js('footer-inline', $INLINEJS); - - return $ret; - - } - - - - - - - - private function imagepickerDefault($path, $parms=array()) - { - $tp = e107::getParser(); - - if(!empty($parms['legacyPath'])) // look in a specific path. - { - $legacyDefault = rtrim($parms['legacyPath'],'/')."/".$path; - $legacyRel = $tp->replaceConstants($legacyDefault); - - if(is_readable($legacyRel)) - { - return array($legacyDefault, $legacyDefault); - } - else - { - // e107::getDebug()->log("Legacy Default:".$legacyDefault); - // e107::getDebug()->log("wasnt found:".$legacyRel); - } - - } - - $path = str_replace('e_MEDIA_IMAGE/','{e_MEDIA_IMAGE}',$path); - - $default_thumb = $tp->createConstants($path, 'nice'); - $default = $tp->createConstants($path, 'mix'); - - return array($default_thumb, $default); - - } - - - /** - * File Picker - * @param string name eg. 'myfield' or 'myfield[]' - * @param mixed default - * @param string label - * @param mixed sc_parameters - */ - function filepicker($name, $default, $label = '', $sc_parameters = '') - { - $tp = e107::getParser(); - $name_id = $this->name2id($name); - - if(is_string($sc_parameters)) - { - if(strpos($sc_parameters, '=') === false) $sc_parameters = 'media='.$sc_parameters; - parse_str($sc_parameters, $sc_parameters); - } - - $cat = vartrue($sc_parameters['media']) ? $tp->toDB($sc_parameters['media']) : "_common_file"; - - $ret = ''; - - if($sc_parameters['data'] === 'array') - { - // Do not use $this->hidden() method - as it will break 'id' value. - $ret .= ""; - $ret .= ""; - $ret .= ""; - - $default = $default['path']; - } - else - { - $ret .= ""; - } - - - $default_label = ($default) ? $default : LAN_CHOOSE_FILE; - $label = "".basename($default_label).""; - - $sc_parameters['mode'] = 'main'; - $sc_parameters['action'] = 'dialog'; - - - // $ret .= $this->mediaUrl($cat, $label,$name_id,"mode=dialog&action=list"); - $ret .= $this->mediaUrl($cat, $label,$name_id,$sc_parameters); - - - - - return $ret; - - - } - - - - - /** - * Date field with popup calendar // NEW in 0.8/2.0 - * on Submit returns unix timestamp or string value. - * @param string $name the name of the field - * @param integer $datestamp UNIX timestamp - default value of the field - * @param array or str - * @param string $options['type'] date or datetime - * @param string $options['format'] strftime format eg. '%Y-%m-%d' - * @param string $options['timezone'] eg. 'America/Los_Angeles' - intended timezone of the date/time entered. (offsets UTC value) - * @example $frm->datepicker('my_field',time(),'type=date'); - * @example $frm->datepicker('my_field',time(),'type=datetime&inline=1'); - * @example $frm->datepicker('my_field',time(),'type=date&format=yyyy-mm-dd'); - * @example $frm->datepicker('my_field',time(),'type=datetime&format=MM, dd, yyyy hh:ii'); - * @example $frm->datepicker('my_field',time(),'type=datetime&return=string'); - * - * @url http://trentrichardson.com/examples/timepicker/ - * @return string - */ - function datepicker($name, $datestamp = false, $options = null) - { - if(vartrue($options) && is_string($options)) - { - parse_str($options,$options); - } - - $type = varset($options['type']) ? trim($options['type']) : "date"; // OR 'datetime' - $dateFormat = varset($options['format']) ? trim($options['format']) :e107::getPref('inputdate', '%Y-%m-%d'); - $ampm = (preg_match("/%l|%I|%p|%P/",$dateFormat)) ? 'true' : 'false'; - $value = null; - $hiddenValue = null; - $useUnix = (isset($options['return']) && ($options['return'] === 'string')) ? 'false' : 'true'; - $id = $this->name2id($name); - $classes = array('date' => 'e-date', 'datetime' => 'e-datetime'); - - if($type == 'datetime' && !varset($options['format'])) - { - $dateFormat .= " ".e107::getPref('inputtime', '%H:%M:%S'); - } - - $dformat = e107::getDate()->toMask($dateFormat); - - // If default value is set. - if ($datestamp && $datestamp !='0000-00-00') // date-field support. - { - if(!is_numeric($datestamp)) - { - $datestamp = strtotime($datestamp); - } - - // Convert date to proper (selected) format. - $hiddenValue = $value = e107::getDate()->convert_date($datestamp, $dformat); - - if ($useUnix === 'true') - { - $hiddenValue = $datestamp; - } - } - - $class = (isset($classes[$type])) ? $classes[$type] : "tbox e-date"; - $size = vartrue($options['size']) ? intval($options['size']) : 40; - $required = vartrue($options['required']) ? "required" : ""; - $firstDay = vartrue($options['firstDay']) ? $options['firstDay'] : 0; - $xsize = (vartrue($options['size']) && !is_numeric($options['size'])) ? $options['size'] : 'xlarge'; - $disabled = vartrue($options['disabled']) ? "disabled" : ""; - $timezone = ''; - - if(!empty($options['timezone'])) // since datetimepicker does not support timezones and assumes the browser timezone is the intended timezone. - { - date_default_timezone_set($options['timezone']); - $targetOffset = date('Z'); - date_default_timezone_set(USERTIMEZONE); - $timezone = "data-date-timezone-offset='".$targetOffset."'"; - } - - $text = ""; - - if(vartrue($options['inline'])) - { - $text .= "
"; - $text .= ""; - } - else - { - $text .= ""; - $ftype = (!empty($options['debug'])) ? 'text' : 'hidden'; - $text .= ""; - } - - // TODO use Library Manager... - e107::css('core', 'bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css', 'jquery'); - e107::js('footer', '{e_WEB}js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js', 'jquery', 4); - e107::js('footer', '{e_WEB}js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js', 'jquery', 5); - - if(e_LANGUAGE !== 'English') - { - e107::js('footer-inline', e107::getDate()->buildDateLocale()); - } - - return $text; - } - - - /** - * Render a simple user dropdown list. - * @param string $name - form field name - * @param null $val - current value - * @param array $options - * @param string $options['group'] if == 'class' then users will be sorted into userclass groups. - * @param string $options['fields'] - * @param string $options['classes'] - single or comma-separated list of user-classes members to include. - * @param string $options['excludeSelf'] = exlude logged in user from list. - * @param string $options['return'] if == 'array' an array is returned. - * @param string $options['return'] if == 'sqlWhere' an sql query is returned. - * @return string select form element. - */ - public function userlist($name, $val=null, $options=array()) - { - - $fields = (!empty($options['fields'])) ? $options['fields'] : "user_id,user_name,user_class"; - $class = (!empty($options['classes'])) ? $options['classes'] : e_UC_MEMBER ; // all users sharing the same class as the logged-in user. - - $class = str_replace(" ","",$class); - - switch ($class) - { - case e_UC_ADMIN: - $where = "user_admin = 1"; - $classList = e_UC_ADMIN; - break; - - case e_UC_MEMBER: - $where = "user_ban = 0"; - $classList = e_UC_MEMBER; - break; - - case e_UC_NOBODY: - return ""; - break; - - case 'matchclass': - $where = "user_class REGEXP '(^|,)(".str_replace(",","|", USERCLASS).")(,|$)'"; - $classList = USERCLASS; - $clist = explode(",",USERCLASS); - if(count($clist) > 1 && !isset($options['group'])) // group classes by default if more than one found. - { - $options['group'] = 'class'; - } - break; - - default: - $where = "user_class REGEXP '(^|,)(".str_replace(",","|", $class).")(,|$)'"; - $classList = $class; - break; - } - - - if(!empty($options['return']) && $options['return'] == 'sqlWhere') // can be used by user.php ajax method.. - { - return $where; - } - - $users = e107::getDb()->retrieve("user",$fields, "WHERE ".$where." ORDER BY user_name LIMIT 1000",true); - - if(empty($users)) - { - return LAN_UNAVAILABLE; - } - - $opt = array(); - - if(!empty($options['group']) && $options['group'] == 'class') - { - $classes = explode(',',$classList); - - foreach($classes as $cls) - { - $cname = e107::getUserClass()->getName($cls); - - $cname = str_replace('_',' ', trim($cname)); - foreach($users as $u) - { - $uclass = explode(',',$u['user_class']); - - if(($classList == e_UC_ADMIN) || ($classList == e_UC_MEMBER) || in_array($cls,$uclass)) - { - $id = $u['user_id']; - - if(!empty($options['excludeSelf']) && ($id == USERID)) - { - continue; - } - - $opt[$cname][$id] = $u['user_name']; - } - } - - - } - - } - else - { - foreach($users as $u) - { - $id = $u['user_id']; - $opt[$id] = $u['user_name']; - } - - } - - - ksort($opt); - - - if(!empty($options['return']) && $options['return'] == 'array') // can be used by user.php ajax method.. - { - return $opt; - } - - return $this->select($name,$opt,$val,$options, varset($options['default'],null)); - - } - - - - /** - * User auto-complete search - * XXX EXPERIMENTAL - subject to change. - * @param string $name_fld field name for user name - * @param string $id_fld field name for user id - * @param string $default_name default user name value - * @param integer $default_id default user id - * @param array|string $options [optional] 'readonly' (make field read only), 'name' (db field name, default user_name) - * @return string HTML text for display - */ - /* - function userpicker($name_fld, $id_fld='', $default_name, $default_id, $options = array()) - { - if(!is_array($options)) - { - parse_str($options, $options); - } - - $default_name = vartrue($default_name, ''); - $default_id = vartrue($default_id, ''); - - $default_options = array(); - if (!empty($default_name)) - { - $default_options = array( - array( - 'value' => $default_id, - 'label' => $default_name, - ), - ); - } - - $defaults['selectize'] = array( - 'loadPath' => e_BASE . 'user.php', - 'create' => false, - 'maxItems' => 1, - 'mode' => 'multi', - 'options' => $default_options, - ); - - //TODO FIXME Filter by userclass. - see $frm->userlist(). - - $options = array_replace_recursive($defaults, $options); - - $ret = $this->text($name_fld, $default_id, 20, $options); - - return $ret; - } - */ - - - /** - * User Field - auto-complete search - * @param string $name form element name - * @param string|array $value comma separated list of user ids or array of userid=>username pairs. - * @param array|string $options [optional] - * @param int $options['limit'] Maximum number of users - * @param string $options['id'] Custom id - * @param string $options['inline'] Inline ID. - * - * @example $frm->userpicker('author', 1); - * @example $frm->userpicker('authors', "1,2,3"); - * @example $frm->userpicker('author', array('user_id'=>1, 'user_name'=>'Admin'); - * @example $frm->userpicker('authors', array(0=>array('user_id'=>1, 'user_name'=>'Admin', 1=>array('user_id'=>2, 'user_name'=>'John')); - * - * @todo $options['type'] = 'select' - dropdown selections box with data returned as array instead of comma-separated. - * @return string HTML text for display - */ - function userpicker($name, $value, $options = array()) - { - if(!is_array($options)) - { - parse_str($options, $options); - } - - $defaultItems = array(); - - if(is_array($value)) - { - if(isset($value[0]))// multiple users. - { - foreach($value as $val) - { - $defaultItems[] = array('value'=>$val['user_id'], 'label'=>$val['user_name']); - } - - } - else // single user - { - $defaultItems[] = array('value'=>$value['user_id'], 'label'=>$value['user_name']); - } - - } - elseif(!empty($value)) /// comma separated with user-id lookup. - { - $tmp = explode(",", $value); - foreach($tmp as $uid) - { - if($user = e107::user($uid)) - { - $defaultItems[] = array('value'=>$user['user_id'], 'label'=>$user['user_name']); - } - } - } - - $parms = array( - 'selectize' => array( - 'loadPath' => e_HTTP.'user.php', - 'create' => false, - 'maxItems' => 1, - 'mode' => 'multi', - 'options' => $defaultItems - ) - ); - - if(!empty($options['limit'])) - { - $parms['selectize']['maxItems'] = intval($options['limit']); - } - - if(!empty($options['id'])) - { - $parms['id'] = $options['id']; - } - - if(!empty($options['inline'])) - { - $parms['selectize']['e_editable'] = $options['inline']; - } - - //TODO FIXME Filter by userclass. - see $frm->userlist(). - - $defValues = array(); - - foreach($defaultItems as $val) - { - $defValues[] = $val['value']; - } - - $parms = array_merge($parms, $options); - - $ret = $this->text($name, implode(",",$defValues), 100, $parms); - - return $ret; - } - - - - - - - /** - * A Rating element - * @var $text - */ - function rate($table,$id,$options=null) - { - $table = preg_replace('/\W/', '', $table); - $id = intval($id); - - return e107::getRate()->render($table, $id, $options); - } - - function like($table,$id,$options=null) - { - $table = preg_replace('/\W/', '', $table); - $id = intval($id); - - return e107::getRate()->renderLike($table,$id,$options); - } - - - /** - * File Upload form element. - * @param $name - * @param array $options (optional) array('multiple'=>1) - * @return string - */ - function file($name, $options = array()) - { - if(e_ADMIN_AREA && empty($options['class'])) - { - $options = array('class'=>'tbox well file'); - } - - $options = $this->format_options('file', $name, $options); - - - - //never allow id in format name-value for text fields - return "get_attributes($options, $name)." />"; - } - - function upload($name, $options = array()) - { - return 'Ready to use upload form fields, optional - file list view'; - } - - function password($name, $value = '', $maxlength = 50, $options = array()) - { - if(is_string($options)) parse_str($options, $options); - - $addon = ""; - $gen = ""; - - if(vartrue($options['generate'])) - { - $gen = ' '.LAN_GENERATE.' '; - - if(empty($options['nomask'])) - { - $gen .= ''.LAN_SHOW.'
'; - } - } - - if(vartrue($options['strength'])) - { - $addon .= "
"; - } - - $options['pattern'] = vartrue($options['pattern'],'[\S].{2,}[\S]'); - $options['required'] = varset($options['required'], 1); - $options['class'] = vartrue($options['class'],'e-password tbox'); - - - e107::js('core', 'password/jquery.pwdMeter.js', 'jquery', 2); - - e107::js('footer-inline', ' - $(".e-password").pwdMeter({ - minLength: 6, - displayGeneratePassword: true, - generatePassText: "Generate", - randomPassLength: 12 - }); - '); - - if(deftrue('BOOTSTRAP')) - { - $options['class'] .= ' form-control'; - } - - if(vartrue($options['size']) && !is_numeric($options['size'])) - { - $options['class'] .= " input-".$options['size']; - unset($options['size']); // don't include in html 'size='. - } - - $type = empty($options['nomask']) ? 'password' : 'text'; - - $options = $this->format_options('text', $name, $options); - - - //never allow id in format name-value for text fields - $text = "get_attributes($options, $name)." />"; - - if(empty($gen) && empty($addon)) - { - return $text; - } - else - { - return "".$text.$gen."".vartrue($addon); - } - - } - - - /** - * Render Pagination using 'nextprev' shortcode. - * @param string $url eg. e_REQUEST_SELF.'?from=[FROM]' - * @param int $total total records - * @param int $from value to replace [FROM] with in the URL - * @param int $perPage number of items per page - * @param array $options template, type, glyphs - * @return string - */ - public function pagination($url='', $total=0, $from=0, $perPage=10, $options=array()) - { - - if(empty($total) || empty($perPage)) - { - return ''; - } - - if(!is_numeric($total)) - { - return ''; - } - - - - require_once(e_CORE."shortcodes/single/nextprev.php"); - - $nextprev = array( - 'tmpl_prefix' => varset($options['template'],'default'), - 'total' => intval($total), - 'amount' => intval($perPage), - 'current' => intval($from), - 'url' => urldecode($url), - 'type' => varset($options['type'],'record'), // page|record - 'glyphs' => vartrue($options['glyphs'],false) // 1|0 - ); - - // e107::getDebug()->log($nextprev); - - return nextprev_shortcode($nextprev); - } - - - - /** - * Render a bootStrap ProgressBar. - * @param string $name - * @param number|string $value - * @param array $options - * @example Use - */ - public function progressBar($name,$value,$options=array()) - { - if(!deftrue('BOOTSTRAP')) // Legacy ProgressBar. - { - $barl = (file_exists(THEME.'images/barl.png') ? THEME_ABS.'images/barl.png' : e_PLUGIN_ABS.'poll/images/barl.png'); - $barr = (file_exists(THEME.'images/barr.png') ? THEME_ABS.'images/barr.png' : e_PLUGIN_ABS.'poll/images/barr.png'); - $bar = (file_exists(THEME.'images/bar.png') ? THEME_ABS.'images/bar.png' : e_PLUGIN_ABS.'poll/images/bar.png'); - - return "
-
-
"; - } - - $class = vartrue($options['class'],''); - $target = $this->name2id($name); - - $striped = (vartrue($options['btn-label'])) ? ' progress-striped active' : ''; - - if(strpos($value,'/')!==false) - { - $label = $value; - list($score,$denom) = explode('/',$value); - - $multiplier = 100 / (int) $denom; - - $value = (int) $score * (int) $multiplier; - $percVal = number_format($value,0).'%'; - } - else - { - $percVal = number_format($value,0).'%'; - $label = $percVal; - } - - if(!empty($options['label'])) - { - $label = $options['label']; - } - - - $text = "
-
"; - $text .= $label; - $text .= "
-
"; - - $loading = vartrue($options['loading'], defset('LAN_LOADING', "Loading")); - - $buttonId = $target.'-start'; - - - - if(vartrue($options['btn-label'])) - { - $interval = vartrue($options['interval'],1000); - $text .= ''.$options['btn-label'].''; - $text .= ' '.LAN_CANCEL.''; - } - - - return $text; - - } - - - /** - * Textarea Element - * @param $name - * @param $value - * @param $rows - * @param $cols - * @param $options - * @param $count - * @return string - */ - function textarea($name, $value, $rows = 10, $cols = 80, $options = array(), $counter = false) - { - if(is_string($options)) parse_str($options, $options); - // auto-height support - - if(empty($options['class'])) - { - $options['class'] = ''; - } - - if(vartrue($options['size']) && !is_numeric($options['size'])) - { - $options['class'] .= " form-control input-".$options['size']; - unset($options['size']); // don't include in html 'size='. - } - elseif(!vartrue($options['noresize'])) - { - $options['class'] = (isset($options['class']) && $options['class']) ? $options['class'].' e-autoheight' : 'tbox col-md-7 span7 e-autoheight form-control'; - } - - $options = $this->format_options('textarea', $name, $options); - -// print_a($options); - //never allow id in format name-value for text fields - return "".(false !== $counter ? $this->hidden('__'.$name.'autoheight_opt', $counter) : ''); - } - - /** - * Bbcode Area. Name, value, template, media-Cat, size, options array eg. counter - * IMPORTANT: $$mediaCat is also used is the media-manager category identifier - * @param string $name - * @param mixed $value - * @param string $template - * @param string $mediaCat _common - * @param string $size : small | medium | large - * @param array $options array(); - * @param bool $options['wysiwyg'] when set to false will disable wysiwyg if active. - * @param string $options['class'] override class. - * @param string $options['id'] - */ - function bbarea($name, $value, $template = '', $mediaCat='_common', $size = 'large', $options = array()) - { - if(is_string($options)) parse_str($options, $options); - //size - large|medium|small - //width should be explicit set by current admin theme - // $size = 'input-large'; - $height = ''; - $cols = 70; - - switch($size) - { - case 'tiny': - $rows = '3'; - $cols = 50; - // $height = "style='height:250px'"; // inline required for wysiwyg - break; - - - case 'small': - $rows = '7'; - $height = "style='height:230px'"; // inline required for wysiwyg - $size = "input-block-level"; - break; - - case 'medium': - $rows = '10'; - - $height = "style='height:375px'"; // inline required for wysiwyg - $size = "input-block-level"; - break; - - case 'large': - default: - $rows = '20'; - $size = 'large input-block-level'; - // $height = "style='height:500px;width:1025px'"; // inline required for wysiwyg - break; - } - - // auto-height support -/* - $bbbar = ''; - $wysiwyg = null; - $wysiwygClass = ' e-wysiwyg'; - - if(isset($options['wysiwyg'])) - { - $wysiwyg = $options['wysiwyg']; - } - - if($wysiwyg === false) - { - $wysiwygClass = ''; - } - - $options['class'] = 'tbox bbarea '.($size ? ' '.$size : '').$wysiwygClass.' e-autoheight form-control'; -*/ - $options['class'] = 'tbox bbarea '.($size ? ' '.$size : '').' e-wysiwyg e-autoheight form-control'; - - if (isset($options['id']) && !empty($options['id'])) - { - $help_tagid = $this->name2id($options['id'])."--preview"; - } - else - { - $help_tagid = $this->name2id($name)."--preview"; - } - - if (!isset($options['wysiwyg'])) - { - $options['wysiwyg'] = true; - } - - //if(e107::wysiwyg(true) === false || $wysiwyg === false) // bbarea loaded, so activate wysiwyg (if enabled in preferences) - if(e107::wysiwyg($options['wysiwyg'],true) === 'bbcode') // bbarea loaded, so activate wysiwyg (if enabled in preferences) - { - $options['other'] = "onselect='storeCaret(this);' onclick='storeCaret(this);' onkeyup='storeCaret(this);' {$height}"; - } - else - { - $options['other'] = " ".$height; - } - - - $counter = vartrue($options['counter'],false); - - $ret = "
-
\n"; - - - if(e107::wysiwyg() === true) // && $wysiwyg !== false) - { - $eParseList = e107::getConfig()->get('e_parse_list'); - - if(!empty($eParseList)) - { - $opts = array( - 'field' => $name, - ); - - foreach($eParseList as $plugin) - { - $hookObj = e107::getAddon($plugin, 'e_parse'); - - if($tmp = e107::callMethod($hookObj, 'toWYSIWYG', $value, $opts)) - { - $value = $tmp; - } - } - } - } - - - $ret .= e107::getBB()->renderButtons($template,$help_tagid); - $ret .= $this->textarea($name, $value, $rows, $cols, $options, $counter); // higher thank 70 will break some layouts. - - $ret .= "
\n"; - - $_SESSION['media_category'] = $mediaCat; // used by TinyMce. - - - - - return $ret; - - // Quick fix - hide TinyMCE links if not installed, dups are handled by JS handler - /* - - e107::getJs()->footerInline(" - if(typeof tinyMCE === 'undefined') - { - \$$('a.e-wysiwyg-switch').invoke('hide'); - } - "); - */ - - - } - - /** - * Render a checkbox - * @param string $name - * @param mixed $value - * @param boolean $checked - * @param mixed $options query-string or array or string for a label. eg. label=Hello&foo=bar or array('label'=>Hello') or 'Hello' - * @return string - */ - function checkbox($name, $value, $checked = false, $options = array()) - { - if(!is_array($options)) - { - if(strpos($options,"=")!==false) - { - parse_str($options, $options); - } - elseif(is_array($options)) - { - // do nothing. - } - else // Assume it's a label. - { - $options = array('label'=>$options); - } - - } - - $labelClass = (!empty($options['inline'])) ? 'checkbox-inline' : 'checkbox'; - $labelTitle = ''; - - $options = $this->format_options('checkbox', $name, $options); - - $options['checked'] = $checked; //comes as separate argument just for convenience - - $text = ""; - - $active = ($checked === true) ? " active" : ""; // allow for styling if needed. - - if(!empty($options['label'])) // add attributes to "; - } - - function help($text) - { - return !empty($text) ? '
'.$text.'
' : ''; - } - - function select_open($name, $options = array()) - { - - if(!is_array($options)) parse_str($options, $options); - - - if(!empty($options['size']) && !is_numeric($options['size'])) - { - if(!empty($options['class'])) - { - $options['class'] .= " form-control input-".$options['size']; - } - else - { - $options['class'] = "form-control input-".$options['size']; - } - - unset($options['size']); // don't include in html 'size='. - } - - - $options = $this->format_options('select', $name, $options); - - return " - - - - - - - - -
-
- - - - - - - */ - } - - - /** - * @param $name - * @param null $current_value - * @param null $uc_options - * @param array $select_options multiple, default - * @param array $opt_options - * @return string - */ - function uc_select($name, $current_value=null, $uc_options=null, $select_options = array(), $opt_options = array()) - { - -/* var_dump($name); - var_dump($current_value); -var_dump($uc_options); -var_dump($select_options);*/ - - - if(!empty($select_options['multiple']) && substr($name,-1) != ']') - { - $name .= '[]'; - } - - if(($current_value === null || $current_value === '') && !empty($uc_options)) // make the first in the opt list the default value. - { - $tmp = explode(",", $uc_options); - $current_value = e107::getUserClass()->getClassFromKey($tmp[0]); - - if(isset($select_options['default'])) - { - $current_value = (int) $select_options['default']; - } - } - - if(!empty($current_value) && !is_numeric($current_value)) // convert name to id. - { - //$current_value = $this->_uc->getID($current_value); - // issue #3249 Accept also comma separated values - if (!is_array($current_value)) - { - $current_value = explode(',', $current_value); - } - $tmp = array(); - foreach($current_value as $val) - { - if (!empty($val)) - { - $tmp[] = !is_numeric($val) ? $this->_uc->getID(trim($val)) : (int) $val; - } - } - $current_value = implode(',', $tmp); - unset($tmp); - } - - $text = $this->select_open($name, $select_options)."\n"; - $text .= $this->_uc->vetted_tree($name, array($this, '_uc_select_cb'), $current_value, $uc_options, $opt_options)."\n"; - $text .= $this->select_close(); - - return $text; - } - - // Callback for vetted_tree - Creates the option list for a selection box - function _uc_select_cb($treename, $classnum, $current_value, $nest_level) - { - $classIndex = abs($classnum); // Handle negative class values - $classSign = (substr($classnum, 0, 1) == '-') ? '-' : ''; - - if($classnum == e_UC_BLANK) - return $this->option(' ', ''); - - $tmp = explode(',', $current_value); - if($nest_level == 0) - { - $prefix = ''; - $style = "font-weight:bold; font-style: italic;"; - } - elseif($nest_level == 1) - { - $prefix = '  '; - $style = "font-weight:bold"; - } - else - { - $prefix = '  '.str_repeat('--', $nest_level - 1).'>'; - $style = ''; - } - return $this->option($prefix.$this->_uc->uc_get_classname($classnum), $classSign.$classIndex, ($current_value !== '' && in_array($classnum, $tmp)), array("style"=>"{$style}"))."\n"; - } - - - function optgroup_open($label, $disabled = false, $options = null) - { - return "\n"; - } - - /** - * "; - } - - - /** - * Use selectbox() instead. - */ - function option_multi($option_array, $selected = false, $options = array()) - { - if(is_string($option_array)) - { - parse_str($option_array, $option_array); - } - - $text = ''; - - if(empty($option_array)) - { - return $this->option('',''); - } - - $opts = $options; - - foreach ((array) $option_array as $value => $label) - { - if(is_array($label)) - { - $text .= $this->optgroup($value, $label, $selected, $options, 0); - } - else - { - $sel = is_array($selected) ? in_array($value, $selected) : ($value == $selected); - - if(!empty($options['optDisabled']) && is_array($options['optDisabled'])) - { - $opts['disabled'] = in_array($value, $options['optDisabled']); - } - - $text .= $this->option($label, $value, $sel, $opts)."\n"; - } - } - - return $text; - } - - - /** - * No compliant, but it works. - * @param $value - * @param $label - * @param $selected - * @param $options - * @param int $level - * @return string - */ - private function optgroup($value, $label, $selected, $options, $level=1) - { - $level++; - $text = $this->optgroup_open($value, null, array('class'=>'level-'.$level)); - - $opts = $options; - - foreach($label as $val => $lab) - { - if(is_array($lab)) - { - $text .= $this->optgroup($val,$lab,$selected,$options,$level); - } - else - { - if(!empty($options['optDisabled']) && is_array($options['optDisabled'])) - { - $opts['disabled'] = in_array($val, $options['optDisabled']); - } - - $text .= $this->option($lab, $val, (is_array($selected) ? in_array($val, $selected) : $selected == $val), $opts)."\n"; - } - - } - - $text .= $this->optgroup_close(); - - return $text; - } - - - - - - function optgroup_close() - { - return "\n"; - } - - function select_close() - { - return ""; - } - - function hidden($name, $value, $options = array()) - { - $options = $this->format_options('hidden', $name, $options); - - return "get_attributes($options, $name, $value)." />"; - } - - /** - * Generate hidden security field - * @return string - */ - function token() - { - return ""; - } - - function submit($name, $value, $options = array()) - { - $options = $this->format_options('submit', $name, $options); - return "get_attributes($options, $name, $value)." />"; - } - - function submit_image($name, $value, $image, $title='', $options = array()) - { - $tp = e107::getParser(); - - if(!empty($options['icon'])) - { - $customIcon = $options['icon']; - unset($options['icon']); - } - - $options = $this->format_options('submit_image', $name, $options); - switch ($image) - { - case 'edit': - $icon = (e_ADMIN_AREA === true) ? ADMIN_EDIT_ICON : $tp->toIcon("e-edit-32"); - $options['class'] = $options['class'] == 'action' ? 'btn btn-default btn-secondary action edit' : $options['class']; - break; - - case 'delete': - $icon = (e_ADMIN_AREA === true) ? ADMIN_DELETE_ICON : $tp->toIcon('fa-trash.glyph'); - $options['class'] = $options['class'] == 'action' ? 'btn btn-default btn-secondary action delete' : $options['class']; - $options['other'] = 'data-confirm="'.LAN_JSCONFIRM.'"'; - break; - - case 'execute': - $icon = (e_ADMIN_AREA === true) ? ADMIN_EXECUTE_ICON : $tp->toIcon('fa-power-off.glyph'); - $options['class'] = $options['class'] == 'action' ? 'btn btn-default btn-secondary action execute' : $options['class']; - break; - - case 'view': - $icon = $tp->toIcon("e-view-32"); - $options['class'] = $options['class'] == 'action' ? 'btn btn-default btn-secondary action view' : $options['class']; - break; - } - - $options['title'] = $title;//shorthand - - if(!empty($customIcon)) - { - $icon = $customIcon; - } - - return ""; - - - } - - /** - * Alias of admin_button, adds the etrigger_ prefix required for UI triggers - * @see e_form::admin_button() - */ - function admin_trigger($name, $value, $action = 'submit', $label = '', $options = array()) - { - return $this->admin_button('etrigger_'.$name, $value, $action, $label, $options); - } - - - /** - * Generic Button Element. - * @param string $name - * @param string $value - * @param string $action [optional] default is submit - use 'dropdown' for a bootstrap dropdown button. - * @param string $label [optional] - * @param string|array $options [optional] - * @return string - */ - public function button($name, $value, $action = 'submit', $label = '', $options = array()) - { - if(deftrue('BOOTSTRAP') && $action == 'dropdown' && is_array($value)) - { - // $options = $this->format_options('admin_button', $name, $options); - $options['class'] = vartrue($options['class']); - - $align = vartrue($options['align'],'left'); - - $text = '
- - '.($label ? $label : LAN_NO_LABEL_PROVIDED).' - - - -
'; - - return $text; - } - - - - return $this->admin_button($name, $value, $action, $label, $options); - - } - - /** - * Render a Breadcrumb in Bootstrap format. - * @param $array - * @param $array[url] - * @param $array[text] - */ - function breadcrumb($array) - { - if(!is_array($array)){ return; } - - $opt = array(); - - $homeicon = (deftrue('FONTAWESOME')) ? 'fa-home' : 'icon-home.glyph'; - $homeIcon = e107::getParser()->toGlyph($homeicon,false); - - - $opt[] = "".$homeIcon.""; // Add Site-Pref to disable? - - $text = '"; - - // return print_a($opt,true); - - return $text; - - } - - - /** - * Render a direct link admin-edit button on the frontend. - * @param $url - * @param string $perms - * @return string - */ - public function instantEditButton($url, $perms='0') - { - if(deftrue("BOOTSTRAP") && getperms($perms)) - { - return "".e107::getParser()->toGlyph('fa-edit').""; - } - - return ''; - - } - - - - - /** - * Admin Button - for front-end, use button(); - * @param string $name - * @param string $value - * @param string $action [optional] default is submit - * @param string $label [optional] - * @param string|array $options [optional] - * @return string - */ - function admin_button($name, $value, $action = 'submit', $label = '', $options = array()) - { - $btype = 'submit'; - if(strpos($action, 'action') === 0) - { - $btype = 'button'; - } - - if(isset($options['loading']) && ($options['loading'] == false)) - { - unset($options['loading']); - $include = ''; - } - else - { - // $include = (deftrue("FONTAWESOME")) ? "data-loading-icon='fa-spinner' data-disable='true'" : ""; - $include = (deftrue("FONTAWESOME")) ? "data-loading-icon='fa-spinner' " : ""; // data-disable breaks db.php charset Fix. - } - - $confirmation = LAN_JSCONFIRM; - - if(!empty($options['confirm'])) - { - $confirmation = $options['confirm']; - } - - $options = $this->format_options('admin_button', $name, $options); - - $options['class'] = vartrue($options['class']); - $options['class'] .= ' btn ' . $action; - - if(empty($label)) - { - $label = $value; - } - - // Ability to use any kind of button class for the selected action. - if (!$this->defaultButtonClassExists($options['class'])) - { - $options['class'] .= ' ' . $this->getDefaultButtonClassByAction($action); - } - - switch ($action) - { - case 'checkall': - $options['class'] .= ' btn-mini btn-xs'; - break; - - case 'delete': - case 'danger': - - - - $options['other'] = 'data-confirm="'.$confirmation.'"'; - break; - - case 'batch': - case 'batch e-hide-if-js': - // FIXME hide-js shouldn't be here. - break; - - case 'filter': - case 'filter e-hide-if-js': - $options['class'] = 'btn btn-default'; - break; - } - - return ""; - } - - /** - * Helper function to check if a (CSS) class already contains a button class? - * - * @param string $class - * The class we want to check. - * - * @return bool - * True if $class already contains a button class. Otherwise false. - */ - function defaultButtonClassExists($class = '') - { - // Bootstrap button classes. - // @see http://getbootstrap.com/css/#buttons-options - $btnClasses = array( - 'btn-default', - 'btn-primary', - 'btn-success', - 'btn-info', - 'btn-warning', - 'btn-danger', - 'btn-link', - ); - - foreach($btnClasses as $btnClass) { - if(strpos($class, $btnClass, 0) !== false) - { - return true; - } - } - - return false; - } - - - - - - - /** - * Helper function to get default button class by action. - * - * @param string $action - * Action for a button. See button(). - * - * @return string $class - * Default button class. - */ - function getDefaultButtonClassByAction($action) - { - switch($action) - { - case 'update': - case 'create': - case 'import': - case 'submit': - case 'success': - $class = 'btn-success'; - break; - - case 'checkall': - $class = 'btn-default'; - break; - - case 'cancel': - $class = 'btn-default'; - break; - - case 'delete': - case 'danger': - $class = 'btn-danger'; - break; - - case 'execute': - $class = 'btn-success'; - break; - - case 'other': - case 'login': - case 'primary': - $class = 'btn-primary'; - break; - - case 'warning': - case 'confirm': - $class = 'btn-warning'; - break; - - case 'batch': - case 'batch e-hide-if-js': - $class = 'btn-primary'; - break; - - case 'filter': - case 'filter e-hide-if-js': - $class = 'btn-primary'; - break; - - case 'default': - default: - $class = 'btn-default'; - break; - } - - return $class; - } - - function getNext() - { - if(!$this->_tabindex_enabled) return 0; - $this->_tabindex_counter += 1; - return $this->_tabindex_counter; - } - - function getCurrent() - { - if(!$this->_tabindex_enabled) return 0; - return $this->_tabindex_counter; - } - - function resetTabindex($reset = 0) - { - $this->_tabindex_counter = $reset; - } - - function get_attributes($options, $name = '', $value = '') - { - $ret = ''; - // - foreach ($options as $option => $optval) - { - $optval = trim($optval); - switch ($option) - { - - case 'id': - $ret .= $this->_format_id($optval, $name, $value); - break; - - case 'class': - if(!empty($optval)) $ret .= " class='{$optval}'"; - break; - - case 'size': - if($optval) $ret .= " size='{$optval}'"; - break; - - case 'title': - if($optval) $ret .= " title='{$optval}'"; - break; - - case 'label': - if($optval) $ret .= " label='{$optval}'"; - break; - - case 'tabindex': - if($optval) $ret .= " tabindex='{$optval}'"; - elseif(false === $optval || !$this->_tabindex_enabled) break; - else - { - $this->_tabindex_counter += 1; - $ret .= " tabindex='".$this->_tabindex_counter."'"; - } - break; - - case 'readonly': - if($optval) $ret .= " readonly='readonly'"; - break; - - case 'multiple': - if($optval) $ret .= " multiple='multiple'"; - break; - - case 'selected': - if($optval) $ret .= " selected='selected'"; - break; - - case 'maxlength': - if($optval) $ret .= " maxlength='{$optval}'"; - break; - - case 'checked': - if($optval) $ret .= " checked='checked'"; - break; - - case 'disabled': - if($optval) $ret .= " disabled='disabled'"; - break; - - case 'required': - if($optval) $ret .= " required='required'"; - break; - - case 'autofocus': - if($optval) $ret .= " autofocus='autofocus'"; - break; - - case 'placeholder': - if($optval) { - $optval = deftrue($optval, $optval); - $ret .= " placeholder='{$optval}'"; - } - break; - - case 'wrap': - if($optval) $ret .= " wrap='{$optval}'"; - break; - - case 'autocomplete': - if($optval) $ret .= " autocomplete='{$optval}'"; - break; - - case 'pattern': - if($optval) $ret .= " pattern='{$optval}'"; - break; - - case 'other': - if($optval) $ret .= " $optval"; - break; - } - - if(substr($option,0,5) =='data-') - { - $ret .= " ".$option."='{$optval}'"; - } - - } - - return $ret; - } - - /** - * Auto-build field attribute id - * - * @param string $id_value value for attribute id passed with the option array - * @param string $name the name attribute passed to that field - * @param unknown_type $value the value attribute passed to that field - * @return string formatted id attribute - */ - function _format_id($id_value, $name, $value = '', $return_attribute = 'id') - { - if($id_value === false) return ''; - - //format data first - $name = trim($this->name2id($name), '-'); - $value = trim(preg_replace('#[^a-zA-Z0-9\-]#','-', $value), '-'); - //$value = trim(preg_replace('#[^a-z0-9\-]#/i','-', $value), '-'); // This should work - but didn't for me! - $value = trim(str_replace("/","-",$value), '-'); // Why? - if(!$id_value && is_numeric($value)) $id_value = $value; - - // clean - do it better, this could lead to dups - $id_value = trim($id_value, '-'); - - if(empty($id_value) ) return " {$return_attribute}='{$name}".($value ? "-{$value}" : '')."'";// also useful when name is e.g. name='my_name[some_id]' - elseif(is_numeric($id_value) && $name) return " {$return_attribute}='{$name}-{$id_value}'";// also useful when name is e.g. name='my_name[]' - else return " {$return_attribute}='{$id_value}'"; - } - - function name2id($name) - { - $name = strtolower($name); - return rtrim(str_replace(array('[]', '[', ']', '_', '/', ' ','.', '(', ')', '::', ':'), array('-', '-', '', '-', '-', '-', '-','','','-',''), $name), '-'); - } - - /** - * Format options based on the field type, - * merge with default - * - * @param string $type - * @param string $name form name attribute value - * @param array|string $user_options - * @return array merged options - */ - function format_options($type, $name, $user_options=null) - { - if(is_string($user_options)) - { - parse_str($user_options, $user_options); - } - - $def_options = $this->_default_options($type); - - - if(is_array($user_options)) - { - $user_options['name'] = $name; //required for some of the automated tasks - - foreach (array_keys($user_options) as $key) - { - if(!isset($def_options[$key]) && substr($key,0,5)!='data-') unset($user_options[$key]); // data-xxxx exempt //remove it? - } - } - else - { - $user_options = array('name' => $name); //required for some of the automated tasks - } - - return array_merge($def_options, $user_options); - } - - /** - * Get default options array based on the field type - * - * @param string $type - * @return array default options - */ - function _default_options($type) - { - if(isset($this->_cached_attributes[$type])) return $this->_cached_attributes[$type]; - - $def_options = array( - 'id' => '', - 'class' => '', - 'title' => '', - 'size' => '', - 'readonly' => false, - 'selected' => false, - 'checked' => false, - 'disabled' => false, - 'required' => false, - 'autofocus' => false, - 'tabindex' => 0, - 'label' => '', - 'placeholder' => '', - 'pattern' => '', - 'other' => '', - 'autocomplete' => '', - 'maxlength' => '', - 'wrap' => '', - 'multiple' => '', - - // 'multiple' => false, - see case 'select' - ); - - $form_control = (THEME_LEGACY !== true) ? ' form-control' : ''; - - switch ($type) { - case 'hidden': - $def_options = array('id' => false, 'disabled' => false, 'other' => ''); - break; - - case 'text': - $def_options['class'] = 'tbox input-text'.$form_control; - unset($def_options['selected'], $def_options['checked']); - break; - - case 'number': - $def_options['class'] = 'tbox '.$form_control; - break; - - case 'file': - $def_options['class'] = 'tbox file'; - unset($def_options['selected'], $def_options['checked']); - break; - - case 'textarea': - $def_options['class'] = 'tbox textarea'.$form_control; - unset($def_options['selected'], $def_options['checked'], $def_options['size']); - break; - - case 'select': - $def_options['class'] = 'tbox select'.$form_control; - $def_options['multiple'] = false; - unset($def_options['checked']); - break; - - case 'option': - $def_options = array('class' => '', 'selected' => false, 'other' => '', 'disabled' => false, 'label' => ''); - break; - - case 'radio': - //$def_options['class'] = ' '; - $def_options = array('class' => '', 'id'=>''); - unset($def_options['size'], $def_options['selected']); - break; - - case 'checkbox': - unset($def_options['size'], $def_options['selected']); - break; - - case 'submit': - $def_options['class'] = 'button btn btn-primary'; - unset($def_options['checked'], $def_options['selected'], $def_options['readonly']); - break; - - case 'submit_image': - $def_options['class'] = 'action'; - unset($def_options['checked'], $def_options['selected'], $def_options['readonly']); - break; - - case 'admin_button': - unset($def_options['checked'], $def_options['selected'], $def_options['readonly']); - break; - - } - - $this->_cached_attributes[$type] = $def_options; - return $def_options; - } - - function columnSelector($columnsArray, $columnsDefault = '', $id = 'column_options') - { - $columnsArray = array_filter($columnsArray); - - // navbar-header nav-header - // navbar-header nav-header - $text = '"; - - // $text .= "
"; - - $text .= ""; - - - /* - $text = ''; - */ - return $text; - } - - - - - - - - - - - - function colGroup($fieldarray, $columnPref = '') - { - $text = ""; - $count = 0; - foreach($fieldarray as $key=>$val) - { - if ((in_array($key, $columnPref) || $key=='options' || vartrue($val['forced'])) && !vartrue($val['nolist'])) - { - - $class = vartrue($val['class']) ? 'class="'.$val['class'].'"' : ''; - $width = vartrue($val['width']) ? ' style="width:'.$val['width'].'"' : ''; - $text .= ' - '; - $count++; - } - } - - return ' - - '.$text.' - - '; - } - - function thead($fieldarray, $columnPref = array(), $querypattern = '', $requeststr = '') - { - $text = ""; - - $querypattern = filter_var($querypattern, FILTER_SANITIZE_STRING); - if(!$requeststr) $requeststr = rawurldecode(e_QUERY); - $requeststr = filter_var($requeststr, FILTER_SANITIZE_STRING); - - // Recommended pattern: mode=list&field=[FIELD]&asc=[ASC]&from=[FROM] - if(strpos($querypattern,'&')!==FALSE) - { - // we can assume it's always $_GET since that's what it will generate - // more flexible (e.g. pass default values for order/field when they can't be found in e_QUERY) & secure - $tmp = str_replace('&', '&', $requeststr ? $requeststr : e_QUERY); - parse_str($tmp, $tmp); - - $etmp = array(); - parse_str(str_replace('&', '&', $querypattern), $etmp); - } - else // Legacy Queries. eg. main.[FIELD].[ASC].[FROM] - { - $tmp = explode(".", ($requeststr ? $requeststr : e_QUERY)); - $etmp = explode(".", $querypattern); - } - - foreach($etmp as $key => $val) // I'm sure there's a more efficient way to do this, but too tired to see it right now!. - { - if($val == "[FIELD]") - { - $field = varset($tmp[$key]); - } - - if($val == "[ASC]") - { - $ascdesc = varset($tmp[$key]); - } - if($val == "[FROM]") - { - $fromval = varset($tmp[$key]); - } - } - - if(!varset($fromval)){ $fromval = 0; } - - $sorted = varset($ascdesc); - $ascdesc = ($sorted == 'desc') ? 'asc' : 'desc'; - - foreach($fieldarray as $key=>$val) - { - if ((in_array($key, $columnPref) || ($key === 'options' && isset($val['title'])) || (vartrue($val['forced']))) && !vartrue($val['nolist'])) - { - $cl = (vartrue($val['thclass'])) ? " class='".$val['thclass']."'" : ""; - - $aClass = ($key === $field) ? "class='sorted-".$sorted."'" : ""; - - $text .= " - - "; - - if($querypattern!="" && !vartrue($val['nosort']) && $key != "options" && $key != "checkboxes") - { - $from = ($key == $field) ? $fromval : 0; - $srch = array("[FIELD]","[ASC]","[FROM]"); - $repl = array($key,$ascdesc,$from); - $val['url'] = e_SELF."?".str_replace($srch,$repl,$querypattern); - } - - - - $text .= (vartrue($val['url'])) ? "" : ""; // Really this column-sorting link should be auto-generated, or be autocreated via unobtrusive js. - $text .= defset($val['title'], $val['title']); - $text .= ($val['url']) ? "" : ""; - $text .= ($key === "options" && !vartrue($val['noselector'])) ? $this->columnSelector($fieldarray, $columnPref) : ""; - $text .= ($key === "checkboxes") ? $this->checkbox_toggle('e-column-toggle', vartrue($val['toggle'], 'multiselect')) : ""; - - - $text .= " - - "; - } - } - - return " - - ".$text." - - "; - - } - - - /** - * Render Table cells from hooks. - * @param array $data - * @return string - */ - function renderHooks($data) - { - $hooks = e107::getEvent()->triggerHook($data); - - $text = ""; - - if(!empty($hooks)) - { - foreach($hooks as $plugin => $hk) - { - $text .= "\n\n\n"; - - if(!empty($hk)) - { - foreach($hk as $hook) - { - $text .= "\t\t\t\n"; - $text .= "\t\t\t".$hook['caption']."\n"; - $text .= "\t\t\t".$hook['html'].""; - $text .= (varset($hook['help'])) ? "\n".$hook['help']."" : ""; - $text .= "\n\t\t\t\n"; - } - - - } - } - } - - return $text; - } - - - - - /** - * Render Related Items for the current page/news-item etc. - * @param string $type : comma separated list. ie. plugin folder names. - * @param string $tags : comma separated list of keywords to return related items of. - * @param array $curVal. eg. array('page'=> current-page-id-value); - */ - function renderRelated($parm,$tags, $curVal, $template=null) //XXX TODO Cache! - { - - if(empty($tags)) - { - return; - } - - $tags = str_replace(', ',',', $tags); //BC Fix, all tags should be comma separated without spaces ie. one,two NOT one, two - - e107::setRegistry('core/form/related',$tags); // TODO Move to elsewhere so it works without rendering? e107::related() set and get by plugins? - - if(!varset($parm['limit'])) - { - $parm = array('limit' => 5); - } - - if(!varset($parm['types'])) - { - $parm['types'] = 'news'; - } - - if(empty($template)) - { - $TEMPLATE['start'] = "

".defset('LAN_RELATED', 'Related')."

"; - - } - else - { - $TEMPLATE = $template; - } - - - - $tp = e107::getParser(); - - $types = explode(',',$parm['types']); - $list = array(); - - $head = $tp->parseTemplate($TEMPLATE['start'],true); - - foreach($types as $plug) - { - - if(!$obj = e107::getAddon($plug,'e_related')) - { - continue; - } - - $parm['current'] = intval(varset($curVal[$plug])); - - - - - $tmp = $obj->compile($tags,$parm); - - if(count($tmp)) - { - foreach($tmp as $val) - { - - $row = array( - 'RELATED_URL' => $tp->replaceConstants($val['url'],'full'), - 'RELATED_TITLE' => $val['title'], - 'RELATED_IMAGE' => $tp->toImage($val['image']), - 'RELATED_SUMMARY' => $tp->toHTML($val['summary'],true,'BODY') - ); - - $list[] = $tp->simpleParse($TEMPLATE['item'], $row); - - } - } - } - - if(count($list)) - { - return ""; - - // return ""; //XXX Tablerender? - } - - } - - - - /** - * Render Table cells from field listing. - * @param array $fieldarray - eg. $this->fields - * @param array $currentlist - eg $this->fieldpref - * @param array $fieldvalues - eg. $row - * @param string $pid - eg. table_id - * @return string - */ - function renderTableRow($fieldarray, $currentlist, $fieldvalues, $pid) - { - $cnt = 0; - $ret = ''; - - /*$fieldarray = $obj->fields; - $currentlist = $obj->fieldpref; - $pid = $obj->pid;*/ - - $trclass = vartrue($fieldvalues['__trclass']) ? ' class="'.$trclass.'"' : ''; - unset($fieldvalues['__trclass']); - - foreach ($fieldarray as $field => $data) - { - - - // shouldn't happen... test with Admin->Users with user_xup visible and NULL values in user_xup table column before re-enabling this code. - /* - if(!isset($fieldvalues[$field]) && vartrue($data['alias'])) - { - $fieldvalues[$data['alias']] = $fieldvalues[$data['field']]; - $field = $data['alias']; - } - */ - - //Not found - if((!varset($data['forced']) && !in_array($field, $currentlist)) || varset($data['nolist'])) - { - continue; - } - elseif(vartrue($data['type']) != 'method' && !$data['forced'] && !isset($fieldvalues[$field]) && $fieldvalues[$field] !== NULL) - { - $ret .= " - - Not Found! ($field) - - "; - - continue; - } - - $tdclass = vartrue($data['class']); - - if($field == 'checkboxes') $tdclass = $tdclass ? $tdclass.' autocheck e-pointer' : 'autocheck e-pointer'; - - if($field == 'options') $tdclass = $tdclass ? $tdclass.' options' : 'options'; - - - - // there is no other way for now - prepare user data - if('user' == vartrue($data['type']) /* && isset($data['readParms']['idField'])*/) - { - if(varset($data['readParms']) && is_string($data['readParms'])) parse_str($data['readParms'], $data['readParms']); - if(isset($data['readParms']['idField'])) - { - $data['readParms']['__idval'] = $fieldvalues[$data['readParms']['idField']]; - } - elseif(isset($fieldvalues['user_id'])) // Default - { - $data['readParms']['__idval'] = $fieldvalues['user_id']; - } - - if(isset($data['readParms']['nameField'])) - { - $data['readParms']['__nameval'] = $fieldvalues[$data['readParms']['nameField']]; - } - elseif(isset($fieldvalues['user_name'])) // Default - { - $data['readParms']['__nameval'] = $fieldvalues['user_name']; - } - - - } - $value = $this->renderValue($field, varset($fieldvalues[$field]), $data, varset($fieldvalues[$pid])); - - - - if($tdclass) - { - $tdclass = ' class="'.$tdclass.'"'; - } - $ret .= ' - - '.$value.' - - '; - - $cnt++; - } - - if($cnt) - { - return ' - - '.$ret.' - - '; - } - - return ''; - } - - /** - * Inline Token - * @return string - */ - private function inlineToken() - { - $this->_inline_token = $this->_inline_token ?: - password_hash(session_id(), PASSWORD_DEFAULT, ['cost' => 04]); - return $this->_inline_token; - } - - /** - * Create an Inline Edit link. - * @param string $dbField : field being edited - * @param int $pid : primary ID of the row being edited. - * @param string $fieldName - Description of the field name (caption) - * @param mixed $curVal : existing value of in the field - * @param mixed $linkText : existing value displayed - * @param string $type text|textarea|select|date|checklist - * @param array $array : array data used in dropdowns etc. - */ - public function renderInline($dbField, $pid, $fieldName, $curVal, $linkText, $type='text', $array=null, $options=array()) - { - $jsonArray = array(); - - if(!empty($array)) - { - foreach($array as $k=>$v) - { - $jsonArray[$k] = str_replace("'", "`", $v); - } - } - - $source = e107::getParser()->toJSON($jsonArray, true); - - $mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); - - if(!isset($options['url'])) - { - $options['url'] = e_SELF."?mode={$mode}&action=inline&id={$pid}&ajax_used=1"; - } - - if(!empty($pid)) - { - $options['pk'] = $pid; - } - - $title = varset($options['title'] , (LAN_EDIT." ".$fieldName)); - $class = varset($options['class'] ,''); - - unset( $options['title']); - - $text = "inlineToken(); - - if(!empty($options)) - { - foreach($options as $k=>$opt) - { - if(!empty($opt)) - { - $text .= " data-".$k."='".$opt."'"; - } - } - } - - $text .= ">".$linkText.""; - - return $text; - } - - /** - * Check if a value should be linked and wrap in tag if required. - * @todo global pref for the target option? - * @param mixed $value - * @param array $parms - * @param $id - * @return string - */ - private function renderLink($value, $parms, $id=null) - { - if(empty($parms['link']) && empty($parms['url'])) - { - return $value; - } - - $dialog = vartrue($parms['target']) =='dialog' ? " e-modal" : ""; // iframe - $ext = vartrue($parms['target']) =='blank' ? " rel='external' " : ""; // new window - $modal = vartrue($parms['target']) =='modal' ? " data-toggle='modal' data-cache='false' data-target='#uiModal' " : ""; - - - if(!empty($parms['url'])) // ie. use e_url.php - { - $plugin = $this->getController()->getPluginName(); - $data = $this->getController()->getListModel()->getData(); - $link = e107::url($plugin,$parms['url'],$data); - } - else // old way. - { - $tp = e107::getParser(); - - $link = str_replace('[id]',$id,$parms['link']); - $link = $tp->replaceConstants($link); // SEF URL is not important since we're in admin. - - - if($parms['link'] === 'sef' && $this->getController()->getListModel()) - { - $model = $this->getController()->getListModel(); - - if(!$model->getUrl()) - { - $model->setUrl($this->getController()->getUrl()); - } - // assemble the url - $link = $model->url(null); - } - elseif(!empty($data[$parms['link']])) // support for a field-name as the link. eg. link_url. - { - $data = $this->getController()->getListModel()->getData(); - $link = $tp->replaceConstants(vartrue($data[$parms['link']])); - } - } - // in case something goes wrong... - if($link) - { - return "".$value.""; - } - - return $value; - - } - - private function renderOptions($parms, $value='', $id, $attributes) - { - $tp = e107::getParser(); - $cls = false; - - $editIconDefault = deftrue('ADMIN_EDIT_ICON', $tp->toGlyph('fa-edit')); - $deleteIconDefault = deftrue('ADMIN_DELETE_ICON', $tp->toGlyph('fa-trash')); -/* - if($attributes['grid']) - { - $editIconDefault = $tp->toGlyph('fa-edit'); - $deleteIconDefault = $tp->toGlyph('fa-trash'); - } -*/ - - $sf = $this->getController()->getSortField(); - - if(!isset($parms['sort']) && !empty($sf)) - { - $parms['sort'] = true; - } - - $value = "
"; - - if(!empty($parms['sort']) && empty($attributes['grid'])) - { - $mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); - $from = intval(vartrue($_GET['from'],0)); - $value .= "".ADMIN_SORT_ICON." "; - } - - - if(varset($parms['editClass'])) - { - $cls = (deftrue($parms['editClass'])) ? constant($parms['editClass']) : $parms['editClass']; - } - - if((false === $cls || check_class($cls)) && varset($parms['edit'],1) == 1) - { - - parse_str(str_replace('&', '&', e_QUERY), $query); //FIXME - FIX THIS - // keep other vars in tact - $query['action'] = 'edit'; - $query['id'] = $id; - - - if(!empty($parms['target']) && $parms['target']=='modal') - { - $eModal = " e-modal "; - $eModalCap = !empty($parms['modalCaption']) ? "data-modal-caption='".$parms['modalCaption']."'" : "data-modal-caption='#".$id."'"; - $query['iframe'] = 1; - } - else - { - $eModal = ""; - $eModalCap = ""; - } - - if(!empty($parms['modalSubmit'])) - { - $eModalCap .= " data-modal-submit='true'"; - } - - $query = http_build_query($query, null, '&'); - $value .= " - ".$editIconDefault.""; - } - - $delcls = !empty($attributes['noConfirm']) ? ' no-confirm' : ''; - if(varset($parms['deleteClass']) && varset($parms['delete'],1) == 1) - { - $cls = (deftrue($parms['deleteClass'])) ? constant($parms['deleteClass']) : $parms['deleteClass']; - - if(check_class($cls)) - { - $parms['class'] = 'action delete btn btn-default'.$delcls; - unset($parms['deleteClass']); - $parms['icon'] = $deleteIconDefault; - $value .= $this->submit_image('etrigger_delete['.$id.']', $id, 'delete', LAN_DELETE.' [ ID: '.$id.' ]', $parms); - } - } - else - { - $parms['class'] = 'action delete btn btn-default'.$delcls; - $parms['icon'] = $deleteIconDefault; - $value .= $this->submit_image('etrigger_delete['.$id.']', $id, 'delete', LAN_DELETE.' [ ID: '.$id.' ]', $parms); - } - - //$attributes['type'] = 'text'; - $value .= "
"; - - return $value; - - } - - /** - * Render Field Value - * @param string $field field name - * @param mixed $value field value - * @param array $attributes field attributes including render parameters, element options - see e_admin_ui::$fields for required format - * @return string - */ - function renderValue($field, $value, $attributes, $id = 0) - { - - - if(!empty($attributes['multilan']) && is_array($value)) - { - $value = varset($value[e_LANGUAGE],''); - } - - $parms = array(); - if(isset($attributes['readParms'])) - { - if(!is_array($attributes['readParms'])) parse_str($attributes['readParms'], $attributes['readParms']); - $parms = $attributes['readParms']; - } - - // @see custom fields in cpage which accept json params. - if(!empty($attributes['writeParms']) && $tmpOpt = e107::getParser()->isJSON($attributes['writeParms'])) - { - $attributes['writeParms'] = $tmpOpt; - unset($tmpOpt); - } - - - - if(!empty($attributes['inline'])) $parms['editable'] = true; // attribute alias - if(!empty($attributes['sort'])) $parms['sort'] = true; // attribute alias - - if(!empty($parms['type'])) // Allow the use of a different type in readMode. eg. type=method. - { - $attributes['type'] = $parms['type']; - } - - - - - $this->renderValueTrigger($field, $value, $parms, $id); - - $tp = e107::getParser(); - switch($field) // special fields - { - case 'options': - - if(!empty($attributes['type']) && ($attributes['type'] == "method")) // Allow override with 'options' function. - { - $attributes['mode'] = "read"; - if(isset($attributes['method']) && $attributes['method'] && method_exists($this, $attributes['method'])) - { - $method = $attributes['method']; - return $this->$method($parms, $value, $id, $attributes); - - } - elseif(method_exists($this, 'options')) - { - //return $this->options($field, $value, $attributes, $id); - // consistent method arguments, fixed in admin cron administration - $attributes['type'] = null; // prevent infinite loop. - - return $this->options($parms, $value, $id, $attributes); - } - } - - if(!$value) - { - $value = $this->renderOptions($parms, $value, $id, $attributes); - } - - return $value; - break; - - case 'checkboxes': - - //$attributes['type'] = 'text'; - if(empty($attributes['writeParms'])) // avoid comflicts with a field called 'checkboxes' - { - $value = $this->checkbox(vartrue($attributes['toggle'], 'multiselect').'['.$id.']', $id); - return $value; - } - - - break; - } - - switch($attributes['type']) - { - case 'number': - if(!$value) $value = '0'; - - if($parms) - { - if(!isset($parms['sep'])) $value = number_format($value, varset($parms['decimals'],0)); - else $value = number_format($value, $parms['decimals'], vartrue($parms['point'], '.'), vartrue($parms['sep'], ' ')); - } - - if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up - { - $value = $this->renderInline($field,$id,$attributes['title'],$value, $value); - } - elseif(!empty($parms['link'])) - { - $value = $this->renderLink($value,$parms,$id); - } - - - $value = vartrue($parms['pre']).$value.vartrue($parms['post']); - // else same - break; - - case 'country': - - $_value = $this->getCountry($value); - - if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up - { - $arr = $this->getCountry(); - $value = $this->renderInline($field,$id,$attributes['title'],$value, $_value, 'select', $arr); - } - else - { - $value = $_value; - } - - break; - - case 'ip': - //$e107 = e107::getInstance(); - $value = "".e107::getIPHandler()->ipDecode($value).'';; - // else same - break; - - case 'templates': - case 'layouts': - - if(!empty($attributes['writeParms'])) - { - if(is_string($attributes['writeParms'])) parse_str($attributes['writeParms'], $attributes['writeParms']); - } - - if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up - { - $wparms = $attributes['writeParms']; - - $location = vartrue($wparms['plugin']); // empty - core - $ilocation = vartrue($wparms['id'], $location); // omit if same as plugin name - $where = vartrue($wparms['area'], 'front'); //default is 'front' - $filter = varset($wparms['filter']); - $merge = isset($wparms['merge']) ? (bool) $wparms['merge'] : true; - - $layouts = e107::getLayouts($location, $ilocation, $where, $filter, $merge, false); - - $label = varset($layouts[$value], $value); - - $value = $this->renderInline($field, $id, $attributes['title'], $value, $label, 'select', $layouts); - } - - $value = vartrue($parms['pre']) . $value . vartrue($parms['post']); - break; - - case 'checkboxes': - case 'comma': - case 'dropdown': - // XXX - should we use readParams at all here? see writeParms check below - - if($parms && is_array($parms)) // FIXME - add support for multi-level arrays (option groups) - { - //FIXME return no value at all when 'editable=1' is a readParm. See FAQs templates. - // $value = vartrue($parms['pre']).vartrue($parms[$value]).vartrue($parms['post']); - // break; - } - - // NEW - multiple (array values) support - // FIXME - add support for multi-level arrays (option groups) - if(!is_array($attributes['writeParms'])) parse_str($attributes['writeParms'], $attributes['writeParms']); - $wparms = $attributes['writeParms']; - - if(!is_array(varset($wparms['__options']))) parse_str($wparms['__options'], $wparms['__options']); - - if(!empty($wparms['optArray'])) - { - $fopts = $wparms; - $wparms = $fopts['optArray']; - unset($fopts['optArray']); - $wparms['__options'] = $fopts; - } - - - $opts = $wparms['__options']; - unset($wparms['__options']); - $_value = $value; - - if($attributes['type'] == 'checkboxes' || $attributes['type'] == 'comma') - { - $opts['multiple'] = true; - } - - if(!empty($opts['multiple'])) - { - $ret = array(); - $value = is_array($value) ? $value : explode(',', $value); - foreach ($value as $v) - { - if(isset($wparms[$v])) $ret[] = $wparms[$v]; - } - $value = implode(', ', $ret); - - - } - else - { - $ret = ''; - if(isset($wparms[$value])) $ret = $wparms[$value]; - $value = $ret; - } - - $value = ($value ? vartrue($parms['pre']).defset($value, $value).vartrue($parms['post']) : ''); - - if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up - { - $xtype = ($attributes['type'] == 'dropdown') ? 'select' : 'checklist'; - $value = $this->renderInline($field, $id, $attributes['title'], $_value, $value, $xtype, $wparms); - } - - // return ; - break; - - case 'radio': - - - if($parms && isset($parms[$value])) // FIXME - add support for multi-level arrays (option groups) - { - $value = vartrue($parms['pre']).vartrue($parms[$value]).vartrue($parms['post']); - break; - } - - if(!is_array($attributes['writeParms'])) parse_str($attributes['writeParms'], $attributes['writeParms']); - - if(!empty($attributes['writeParms']['optArray'])) - { - $radioValue = $attributes['writeParms']['optArray'][$value]; - - if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up - { - $radioValue = $this->renderInline($field, $id, $attributes['title'], $value, $radioValue, 'select', $attributes['writeParms']['optArray']); - } - } - else - { - $radioValue = vartrue($attributes['writeParms'][$value]); - } - - - $value = vartrue($attributes['writeParms']['__options']['pre']).$radioValue.vartrue($attributes['writeParms']['__options']['post']); - break; - - case 'tags': - if(!empty($parms['constant'])) - { - $value = defset($value, $value); - } - - if(!empty($parms['truncate'])) - { - $value = $tp->text_truncate($value, $parms['truncate'], '...'); - } - elseif(!empty($parms['htmltruncate'])) - { - $value = $tp->html_truncate($value, $parms['htmltruncate'], '...'); - } - if(!empty($parms['wrap'])) - { - $value = $tp->htmlwrap($value, (int) $parms['wrap'], varset($parms['wrapChar'], ' ')); - } - - $value = $this->renderLink($value,$parms,$id); - /* - if(!empty($parms['link']) && $id) - { - $link = str_replace('[id]', $id, $parms['link']); - $link = $tp->replaceConstants($link); // SEF URL is not important since we're in admin. - - $dialog = vartrue($parms['target']) == 'dialog' ? " e-dialog" : ""; // iframe - $ext = vartrue($parms['target']) == 'blank' ? " rel='external' " : ""; // new window - $modal = vartrue($parms['target']) == 'modal' ? " data-toggle='modal' data-cache='false' data-target='#uiModal' " : ""; - - if($parms['link'] == 'sef' && $this->getController()->getListModel()) - { - $model = $this->getController()->getListModel(); - // copy url config - if(!$model->getUrl()) - { - $model->setUrl($this->getController()->getUrl()); - } - // assemble the url - $link = $model->url(); - } - - elseif(vartrue($data[$parms['link']])) // support for a field-name as the link. eg. link_url. - { - $link = $tp->replaceConstants(vartrue($data[$parms['link']])); - } - - // in case something goes wrong... - if($link) - { - $value = "" . $value . ""; - } - }*/ - - if(empty($value)) - { - $value = '-'; - $setValue = "data-value=''"; - } - else - { - $setValue = ""; - - if($attributes['type'] == 'tags' && !empty($value)) - { - $setValue = "data-value='" . $value . "'"; - $value = str_replace(",", ", ", $value); // add spaces so it wraps, but don't change the actual values. - } - } - - - if(!vartrue($attributes['noedit']) && vartrue($parms['editable']) && !vartrue($parms['link'])) // avoid bad markup, better solution coming up - { - $options['selectize'] = array( - 'create' => true, - 'maxItems' => vartrue($parms['maxItems'], 7), - 'mode' => 'multi', - 'e_editable' => $field . '_' . $id, - ); - - $tpl = $this->text($field, $value, 80, $options); - - $mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); - $value = "" . $value . ""; - } - - $value = vartrue($parms['pre']) . $value . vartrue($parms['post']); - break; - - case 'text': - - if(!empty($parms['constant'])) - { - $value = defset($value,$value); - } - - if(vartrue($parms['truncate'])) - { - $value = $tp->text_truncate($value, $parms['truncate'], '...'); - } - elseif(vartrue($parms['htmltruncate'])) - { - $value = $tp->html_truncate($value, $parms['htmltruncate'], '...'); - } - if(vartrue($parms['wrap'])) - { - $value = $tp->htmlwrap($value, (int)$parms['wrap'], varset($parms['wrapChar'], ' ')); - } - - $value = $this->renderLink($value,$parms,$id); - - /* - if(vartrue($parms['link']) && $id) - { - $link = str_replace('[id]',$id,$parms['link']); - $link = $tp->replaceConstants($link); // SEF URL is not important since we're in admin. - - $dialog = vartrue($parms['target']) =='dialog' ? " e-dialog" : ""; // iframe - $ext = vartrue($parms['target']) =='blank' ? " rel='external' " : ""; // new window - $modal = vartrue($parms['target']) =='modal' ? " data-toggle='modal' data-cache='false' data-target='#uiModal' " : ""; - - if($parms['link'] == 'sef' && $this->getController()->getListModel()) - { - $model = $this->getController()->getListModel(); - // copy url config - if(!$model->getUrl()) $model->setUrl($this->getController()->getUrl()); - // assemble the url - $link = $model->url(null); - } - elseif(vartrue($data[$parms['link']])) // support for a field-name as the link. eg. link_url. - { - $link = $tp->replaceConstants(vartrue($data[$parms['link']])); - } - - // in case something goes wrong... - if($link) $value = "".$value.""; - }*/ - - if(empty($value)) - { - $value = '-'; - $setValue = "data-value=''"; - } - else - { - $setValue = ""; - - if($attributes['type'] == 'tags' && !empty($value)) - { - $setValue = "data-value='".$value."'"; - $value = str_replace(",", ", ", $value); // add spaces so it wraps, but don't change the actual values. - } - } - - - if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up - { - $value = $this->renderInline($field,$id,$attributes['title'],$value, $value); - } - - $value = vartrue($parms['pre']).$value.vartrue($parms['post']); - break; - - - - case 'bbarea': - case 'textarea': - - - if($attributes['type'] == 'textarea' && !vartrue($attributes['noedit']) && vartrue($parms['editable']) && !vartrue($parms['link'])) // avoid bad markup, better solution coming up - { - return $this->renderInline($field,$id,$attributes['title'],$value,substr($value,0,50)."...",'textarea'); //FIXME. - } - - - $expand = '...'; - $toexpand = false; - if($attributes['type'] == 'bbarea' && !isset($parms['bb'])) $parms['bb'] = true; //force bb parsing for bbareas - $elid = trim(str_replace('_', '-', $field)).'-'.$id; - if(!vartrue($parms['noparse'])) $value = $tp->toHTML($value, (vartrue($parms['bb']) ? true : false), vartrue($parms['parse'])); - if(vartrue($parms['expand']) || vartrue($parms['truncate']) || vartrue($parms['htmltruncate'])) - { - $ttl = vartrue($parms['expand']); - if($ttl == 1) - { - $dataAttr = "data-text-more='" . LAN_MORE . "' data-text-less='" . LAN_LESS . "'"; - $ttl = $expand.""; - } - - $expands = ''.defset($ttl, $ttl).""; - } - - $oldval = $value; - if(vartrue($parms['truncate'])) - { - $value = $oldval = strip_tags($value); - $value = $tp->text_truncate($value, $parms['truncate'], ''); - $toexpand = $value != $oldval; - } - elseif(vartrue($parms['htmltruncate'])) - { - $value = $tp->html_truncate($value, $parms['htmltruncate'], ''); - $toexpand = $value != $oldval; - } - if($toexpand) - { - // force hide! TODO - core style .expand-c (expand container) - $value .= ''; - $value .= varset($expands); // 'More..' button. Keep it at the bottom so it does't cut the sentence. - } - - - - break; - - case 'icon': - - $value = "".$tp->toIcon($value,$parms).""; - - break; - - case 'file': - if(vartrue($parms['base'])) - { - $url = $parms['base'].$value; - } - else $url = e107::getParser()->replaceConstants($value, 'full'); - $name = basename($value); - $value = ''.$name.''; - break; - - case 'image': //js tooltip... - - $thparms = array(); - $createLink = true; - - // Support readParms example: thumb=1&w=200&h=300 - // Support readParms example: thumb=1&aw=80&ah=30 - if(isset($parms['h'])) { $thparms['h'] = intval($parms['h']); } - if(isset($parms['ah'])) { $thparms['ah'] = intval($parms['ah']); } - if(isset($parms['w'])) { $thparms['w'] = intval($parms['w']); } - if(isset($parms['aw'])) { $thparms['aw'] = intval($parms['aw']); } - if(isset($parms['crop'])) { $thparms['crop'] = $parms['crop']; } - - - - if($value) - { - - if(strpos($value,",")!==false) - { - $tmp = explode(",",$value); - $value = $tmp[0]; - unset($tmp); - } - - if(empty($parms['thumb_aw']) && !empty($parms['thumb']) && strpos($parms['thumb'],'x')!==false) - { - list($parms['thumb_aw'],$parms['thumb_ah']) = explode('x',$parms['thumb']); - } - - $vparm = array('thumb'=>'tag','w'=> vartrue($parms['thumb_aw'],'80')); - - if($video = e107::getParser()->toVideo($value,$vparm)) - { - return $video; - } - - $fileOnly = basename($value); - // Not an image but a file. (media manager) - if(!preg_match("/\.(png|jpg|jpeg|gif|PNG|JPG|JPEG|GIF)$/", $fileOnly) && false !== strpos($fileOnly,'.')) - { - $icon = "{e_IMAGE}filemanager/zip_32.png"; - $src = $tp->replaceConstants(vartrue($parms['pre']).$icon, 'abs'); - // return $value; - return e107::getParser()->toGlyph('fa-file','size=2x'); - // return ''.$value.''; - } - - - - if(!empty($parms['thumb'])) - { - - if(isset($parms['link']) && empty($parms['link'])) - { - $createLink = false; - } - - // Support readParms example: thumb=200x300 (wxh) - if(strpos($parms['thumb'],'x')!==false) - { - list($thparms['w'],$thparms['h']) = explode('x',$parms['thumb']); - } - - // Support readParms example: thumb={width} - if(!isset($parms['w']) && is_numeric($parms['thumb']) && '1' != $parms['thumb']) - { - $thparms['w'] = intval($parms['thumb']); - } - elseif(vartrue($parms['thumb_aw'])) // Legacy v2. - { - $thparms['aw'] = intval($parms['thumb_aw']); - } - - if(!empty($parms['legacyPath'])) - { - $thparms['legacy'] = $parms['legacyPath']; - $parms['pre'] = rtrim($parms['legacyPath'],'/').'/'; - } - // return print_a($thparms,true); - - if(!empty($value[0]) && $value[0] === '{') // full path to convert. - { - $src = $tp->replaceConstants($value, 'abs'); - } - else // legacy link without {e_XXX} path. eg. downloads thumbs. - { - $src = $tp->replaceConstants(vartrue($parms['pre']).$value, 'abs'); - } - - $alt = basename($src); - - - $thparms['alt'] = $alt; - $thparms['class'] = "thumbnail e-thumb"; - - // e107::getDebug()->log($value); - - $ttl = $tp->toImage($value, $thparms); - - if($createLink === false) - { - return $ttl; - } - - - $value = ''.$ttl.''; - } - else - { - $src = $tp->replaceConstants(vartrue($parms['pre']).$value, 'abs'); - $alt = $src; //basename($value); - $ttl = vartrue($parms['title'], 'LAN_PREVIEW'); - $value = ''.defset($ttl, $ttl).''; - } - } - elseif(!empty($parms['fallback'])) - { - $value = $parms['fallback']; - $thparms['class'] = "thumbnail e-thumb fallback"; - return $tp->toImage($value, $thparms); - } - break; - - - case 'media': - return e107::getMedia()->previewTag($value, $parms); - break; - - case 'files': - $ret = '
    '; - for ($i=0; $i < 5; $i++) - { - //$k = $key.'['.$i.'][path]'; - $ival = $value[$i]['path']; - $ret .= '
  1. '.$ival.'
  2. '; - } - $ret .= '
'; - $value = $ret; - break; - - case 'datestamp': - $value = $value ? e107::getDate()->convert_date($value, vartrue($parms['mask'], 'short')) : ''; - break; - - case 'date': - - if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up - { - $value = $this->renderInline($field,$id,$attributes['title'],$value, $value); - } - - // just show original value - break; - - case 'userclass': - $dispvalue = $this->_uc->getName($value); - // Inline Editing. - if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up - { - // $mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); - - $uc_options = vartrue($parms['classlist'], 'public,guest,nobody,member,admin,main,classes'); // defaults to 'public,guest,nobody,member,classes' (userclass handler) - unset($parms['classlist']); - - $array = e107::getUserClass()->uc_required_class_list($uc_options); //XXX Ugly looking (non-standard) function naming - TODO discuss name change. - - $value = $this->renderInline($field, $id, $attributes['title'], $value, $dispvalue, 'select', $array, array('placement'=>'left')); - } - else - { - $value = $dispvalue; - } - break; - - case 'userclasses': - // return $value; - $classes = explode(',', $value); - - $uv = array(); - foreach ($classes as $cid) - { - if(!empty($parms['defaultLabel']) && $cid === '') - { - $uv[] = $parms['defaultLabel']; - continue; - } - - $uv[] = $this->_uc->getName($cid); - } - - - - $dispvalue = implode(vartrue($parms['separator'],"
"), $uv); - - // Inline Editing. - if(!vartrue($attributes['noedit']) && vartrue($parms['editable']) && !vartrue($parms['link'])) // avoid bad markup, better solution coming up - { - $uc_options = vartrue($parms['classlist'], 'public,guest, nobody,member,admin,main,classes'); // defaults to 'public,guest,nobody,member,classes' (userclass handler) - $array = e107::getUserClass()->uc_required_class_list($uc_options); //XXX Ugly looking (non-standard) function naming - TODO discuss name change. - - //$mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); - $mode = $tp->filter(vartrue($_GET['mode'], ''),'w'); - $source = str_replace('"',"'",json_encode($array, JSON_FORCE_OBJECT)); - - //NOTE Leading ',' required on $value; so it picks up existing value. - $value = "".$dispvalue.""; - } - else - { - $value = $dispvalue; - } - - unset($parms['classlist']); - - break; - - /*case 'user_name': - case 'user_loginname': - case 'user_login': - case 'user_customtitle': - case 'user_email':*/ - case 'user': - - /*if(is_numeric($value)) - { - $value = e107::user($value); - if($value) - { - $value = $value[$attributes['type']] ? $value[$attributes['type']] : $value['user_name']; - } - else - { - $value = 'not found'; - } - }*/ - $row_id = $id; - // Dirty, but the only way for now - $id = 0; - $ttl = LAN_ANONYMOUS; - - //Defaults to user_id and user_name (when present) and when idField and nameField are not present. - - - // previously set - real parameters are idField && nameField - $id = vartrue($parms['__idval']); - if($value && !is_numeric($value)) - { - $id = vartrue($parms['__idval']); - $ttl = $value; - } - elseif($value && is_numeric($value)) - { - $id = $value; - - if (vartrue($parms['__nameval'])) - { - $ttl = $parms['__nameval']; - } - else - { - $user = e107::user($value); - if (vartrue($user['user_name'])) - { - $ttl = $user['user_name']; - } - } - } - - - if(!empty($parms['link']) && $id && $ttl && is_numeric($id)) - { - // Stay in admin area. - $link = e_ADMIN."users.php?mode=main&action=edit&id=".$id."&readonly=1&iframe=1"; // e107::getUrl()->create('user/profile/view', array('id' => $id, 'name' => $ttl)) - - $value = ''.$ttl.''; - } - else - { - $value = $ttl; - } - - // Inline Editing. - if(!vartrue($attributes['noedit']) && vartrue($parms['editable']) && !vartrue($parms['link'])) // avoid bad markup, better solution coming up - { - // Need a Unique Field ID to store field settings using e107::js('settings'). - $fieldID = $this->name2id($field . '_' . microtime(true)); - // Unique ID for each rows. - $eEditableID = $this->name2id($fieldID . '_' . $row_id); - // $tpl = $this->userpicker($field, '', $ttl, $id, array('id' => $fieldID, 'selectize' => array('e_editable' => $eEditableID))); - - $tpl = $this->userpicker($fieldID, array('user_id'=>$id, 'user_name'=>$ttl), array('id' => $fieldID, 'inline' => $eEditableID)); - $mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); - $value = "" . $ttl . ""; - } - - break; - - case 'bool': - case 'boolean': - $false = vartrue($parms['trueonly']) ? "" : ADMIN_FALSE_ICON; - - if(!vartrue($attributes['noedit']) && vartrue($parms['editable']) && !vartrue($parms['link'])) // avoid bad markup, better solution coming up - { - if(isset($parms['false'])) // custom representation for 'false'. (supports font-awesome when set by css) - { - $false = $parms['false']; - } - else - { - $false = ($value === '') ? "□" : "✗"; - } - - $true = varset($parms['true'],'✓'); // custom representation for 'true'. (supports font-awesome when set by css) - - // $true = '\f00c'; - // $false = '\f00d'; - - $value = intval($value); - - $wparms = (vartrue($parms['reverse'])) ? array(0=>$true, 1=>$false) : array(0=>$false, 1=>$true); - $dispValue = $wparms[$value]; - - return $this->renderInline($field, $id, $attributes['title'], $value, $dispValue, 'select', $wparms, array('class'=>'e-editable-boolean')); - } - - if(vartrue($parms['reverse'])) - { - $value = ($value) ? $false : ADMIN_TRUE_ICON; - } - else - { - $value = $value ? ADMIN_TRUE_ICON : $false; - } - - break; - - case 'url': - if(!$value) break; - $ttl = $value; - if(vartrue($parms['href'])) - { - return $tp->replaceConstants(vartrue($parms['pre']).$value, varset($parms['replace_mod'],'abs')); - } - if(vartrue($parms['truncate'])) - { - $ttl = $tp->text_truncate($value, $parms['truncate'], '...'); - } - $value = "".$ttl.""; - break; - - case 'email': - if(!$value) break; - $ttl = $value; - if(vartrue($parms['truncate'])) - { - $ttl = $tp->text_truncate($value, $parms['truncate'], '...'); - } - $value = "".$ttl.""; - break; - - case 'method': // Custom Function - $method = $attributes['field']; // prevents table alias in method names. ie. u.my_method. - $_value = $value; - - if(!empty($attributes['data']) && $attributes['data'] == 'array') // FIXME @SecretR - please move this to where it should be. - { - $value = e107::unserialize($value); // (saved as array, return it as an array) - } - - $meth = (!empty($attributes['method'])) ? $attributes['method'] : $method; - - if(strpos($meth,'::')!==false) - { - list($className,$meth) = explode('::', $meth); - $cls = new $className(); - } - else - { - $cls = $this; - } - - if(method_exists($cls,$meth)) - { - $parms['field'] = $field; - $mode = (!empty($attributes['mode'])) ? $attributes['mode'] :'read'; - $value = call_user_func_array(array($cls, $meth), array($value, $mode, $parms)); - } - else - { - $className = get_class($cls); - e107::getDebug()->log("Missing Method: ".$className."::".$meth." ".print_a($attributes,true)); - return "Missing Method"; - } - // print_a($attributes); - // Inline Editing. - if(empty($attributes['noedit']) && !empty($parms['editable'])) // avoid bad markup, better solution coming up - { - - $mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); - $methodParms = call_user_func_array(array($this, $meth), array($_value, 'inline', $parms)); - - $inlineParms = (!empty($methodParms['inlineParms'])) ? $methodParms['inlineParms'] : null; - - if(!empty($methodParms['inlineType'])) - { - $attributes['inline'] = $methodParms['inlineType']; - $methodParms = (!empty($methodParms['inlineData'])) ? $methodParms['inlineData'] : null; - } - - - - if(is_string($attributes['inline'])) // text, textarea, select, checklist. - { - switch ($attributes['inline']) - { - - case 'checklist': - $xtype = 'checklist'; - break; - - case 'select': - case 'dropdown': - $xtype = 'select'; - break; - - case 'textarea': - $xtype = 'textarea'; - break; - - - default: - $xtype = 'text'; - $methodParms = null; - break; - } - } - - if(!empty($xtype)) - { - $value = varset($inlineParms['pre'],'').$this->renderInline($field, $id, $attributes['title'], $_value, $value, $xtype, $methodParms,$inlineParms).varset($inlineParms['post'],''); - } - - } - - break; - - case 'hidden': - return (vartrue($parms['show']) ? ($value ? $value : vartrue($parms['empty'])) : ''); - break; - - case 'language': // All Known Languages. - - if(!empty($value)) - { - $_value = $value; - if(strlen($value) === 2) - { - $value = e107::getLanguage()->convert($value); - } - } - - if(!vartrue($attributes['noedit']) && vartrue($parms['editable'])) - { - $wparms = e107::getLanguage()->getList(); - return $this->renderInline($field, $id, $attributes['title'], $_value, $value, 'select', $wparms); - } - - return $value; - - break; - - case 'lanlist': // installed languages. - $options = e107::getLanguage()->getLanSelectArray(); - - if($options) // FIXME - add support for multi-level arrays (option groups) - { - if(!is_array($attributes['writeParms'])) parse_str($attributes['writeParms'], $attributes['writeParms']); - $wparms = $attributes['writeParms']; - if(!is_array(varset($wparms['__options']))) parse_str($wparms['__options'], $wparms['__options']); - $opts = $wparms['__options']; - if($opts['multiple']) - { - $ret = array(); - $value = is_array($value) ? $value : explode(',', $value); - foreach ($value as $v) - { - if(isset($options[$v])) $ret[] = $options[$v]; - } - $value = implode(', ', $ret); - } - else - { - $ret = ''; - if(isset($options[$value])) $ret = $options[$value]; - $value = $ret; - } - $value = ($value ? vartrue($parms['pre']).$value.vartrue($parms['post']) : ''); - } - else - { - $value = ''; - } - break; - - //TODO - order - - default: - $value = $this->renderLink($value,$parms,$id); - //unknown type - break; - } - - return $value; - } - - /** - * Auto-render Form Element - * @param string $key - * @param mixed $value - * @param array $attributes field attributes including render parameters, element options - see e_admin_ui::$fields for required format - * #param array (under construction) $required_data required array as defined in e_model/validator - * @param mixed $attributes['writeParms']['default'] default value when empty (or default option when type='dropdown') - * @param mixed $attributes['writeParms']['defaultValue'] default option value when type='dropdown' - * @param mixed $attributes['writeParms']['empty'] default value when value is empty (dropdown and hidden only right now) - * @return string - */ - function renderElement($key, $value, $attributes, $required_data = array(), $id = 0) - { - $tp = e107::getParser(); - - $parms = vartrue($attributes['writeParms'], array()); - - if($tmpOpt = $tp->isJSON($parms)) - { - $parms = $tmpOpt; - unset($tmpOpt); - } - - if(is_string($parms)) parse_str($parms, $parms); - - $ajaxParms = array(); - - if(!empty($parms['ajax'])) - { - $ajaxParms['data-src'] = varset($parms['ajax']['src']); - $ajaxParms['data-target'] = varset($parms['ajax']['target']); - $ajaxParms['data-method'] = varset($parms['ajax']['method'], 'html'); - $ajaxParms['data-loading'] = varset($parms['ajax']['loading'], 'fa-spinner'); //$tp->toGlyph('fa-spinner', array('spin'=>1)) - - unset($attributes['writeParms']['ajax']); - - // e107::getDebug()->log($parms['ajax']); - } - - if(!empty($attributes['multilan'])) - { - $value = is_array($value) ? varset($value[e_LANGUAGE],'') : $value; - $parms['post'] = "".$tp->toGlyph('fa-language')."".varset($parms['post']); - $key = $key.'['.e_LANGUAGE.']'; - } - - if(empty($value) && !empty($parms['default']) && $attributes['type'] !== 'dropdown') // Allow writeParms to set default value. - { - $value = $parms['default']; - } - - // Two modes of read-only. 1 = read-only, but only when there is a value, 2 = read-only regardless. - if(vartrue($attributes['readonly']) && (vartrue($value) || vartrue($attributes['readonly'])===2)) // quick fix (maybe 'noedit'=>'readonly'?) - { - if(vartrue($attributes['writeParms'])) // eg. different size thumbnail on the edit page. - { - $attributes['readParms'] = $attributes['writeParms']; - } - return $this->renderValue($key, $value, $attributes).$this->hidden($key, $value); // - } - - // FIXME standard - writeParams['__options'] is introduced for list elements, bundle adding to writeParms is non reliable way - $writeParamsOptionable = array('dropdown', 'comma', 'radio', 'lanlist', 'language', 'user'); - $writeParamsDisabled = array('layouts', 'templates', 'userclass', 'userclasses'); - - // FIXME it breaks all list like elements - dropdowns, radio, etc - if(vartrue($required_data[0]) || vartrue($attributes['required'])) // HTML5 'required' attribute - { - // FIXME - another approach, raise standards, remove checks - if(in_array($attributes['type'], $writeParamsOptionable)) - { - $parms['__options']['required'] = 1; - } - elseif(!in_array($attributes['type'], $writeParamsDisabled)) - { - $parms['required'] = 1; - } - } - - // FIXME it breaks all list like elements - dropdowns, radio, etc - if(vartrue($required_data[3]) || vartrue($attributes['pattern'])) // HTML5 'pattern' attribute - { - // FIXME - another approach, raise standards, remove checks - if(in_array($attributes['type'], $writeParamsOptionable)) - { - $parms['__options']['pattern'] = vartrue($attributes['pattern'], $required_data[3]); - } - elseif(!in_array($attributes['type'], $writeParamsDisabled)) - { - $parms['pattern'] = vartrue($attributes['pattern'], $required_data[3]); - } - } - - - - // XXX Fixes For the above. - use optArray variable. eg. $field['key']['writeParms']['optArray'] = array('one','two','three'); - if(($attributes['type'] == 'dropdown' || $attributes['type'] == 'radio' || $attributes['type'] == 'checkboxes') && !empty($parms['optArray'])) - { - $fopts = $parms; - $parms = $fopts['optArray']; - unset($fopts['optArray']); - $parms['__options'] = $fopts; - } - - $this->renderElementTrigger($key, $value, $parms, $required_data, $id); - - switch($attributes['type']) - { - case 'number': - $maxlength = vartrue($parms['maxlength'], 255); - unset($parms['maxlength']); - if(!vartrue($parms['size'])) $parms['size'] = 'small'; - if(!vartrue($parms['class'])) $parms['class'] = 'tbox number e-spinner '; - if(!$value) $value = '0'; - $ret = vartrue($parms['pre']).$this->number($key, $value, $maxlength, $parms).vartrue($parms['post']); - break; - - case 'country': - $ret = vartrue($parms['pre']).$this->country($key, $value, $parms).vartrue($parms['post']); - break; - - case 'ip': - $ret = vartrue($parms['pre']).$this->text($key, e107::getIPHandler()->ipDecode($value), 32, $parms).vartrue($parms['post']); - break; - - case 'email': - $maxlength = vartrue($parms['maxlength'], 255); - unset($parms['maxlength']); - $ret = vartrue($parms['pre']).$this->email($key, $value, $maxlength, $parms).vartrue($parms['post']); // vartrue($parms['__options']) is limited. See 'required'=>true - break; - - case 'url': - $maxlength = vartrue($parms['maxlength'], 255); - unset($parms['maxlength']); - $ret = vartrue($parms['pre']).$this->url($key, $value, $maxlength, $parms).vartrue($parms['post']); // vartrue($parms['__options']) is limited. See 'required'=>true - - break; - // case 'email': - - case 'password': // encrypts to md5 when saved. - $maxlength = vartrue($parms['maxlength'], 255); - unset($parms['maxlength']); - if(!isset($parms['required'])) - { - - $parms['required'] = false; - } - $ret = vartrue($parms['pre']).$this->password($key, $value, $maxlength, $parms).vartrue($parms['post']); // vartrue($parms['__options']) is limited. See 'required'=>true - - break; - - case 'text': - case 'progressbar': - - $maxlength = vartrue($parms['maxlength'], 255); - unset($parms['maxlength']); - - if(!empty($parms['sef']) && e_LANGUAGE != "Japanese" && e_LANGUAGE != "Korean" && e_LANGUAGE != "Hebrew") // unsupported languages.(FIXME there are more) - { - $sefSource = $this->name2id($parms['sef']); - $sefTarget = $this->name2id($key); - if(!empty($parms['tdClassRight'])) - { - $parms['tdClassRight'] .= 'input-group'; - } - else - { - $parms['tdClassRight'] = 'input-group'; - } - - $parms['post'] = "".LAN_GENERATE.""; - } - - if(!empty($parms['password'])) // password mechanism without the md5 storage. - { - $ret = vartrue($parms['pre']).$this->password($key, $value, $maxlength, $parms).vartrue($parms['post']); - } - - else - { - $ret = vartrue($parms['pre']).$this->text($key, $value, $maxlength, $parms).vartrue($parms['post']); // vartrue($parms['__options']) is limited. See 'required'=>true - } - - - if(!empty($attributes['multilan'])) - { - $msize = vartrue($parms['size'], 'xxlarge'); - $ret = "".$ret.""; - } - - break; - - case 'tags': - $maxlength = vartrue($parms['maxlength'], 255); - $ret = vartrue($parms['pre']).$this->tags($key, $value, $maxlength, $parms).vartrue($parms['post']); // vartrue($parms['__options']) is limited. See 'required'=>true - break; - - case 'textarea': - $text = ""; - if(vartrue($parms['append']) && vartrue($value)) // similar to comments - TODO TBD. a 'comment' field type may be better. - { - $attributes['readParms'] = 'bb=1'; - - $text = $this->renderValue($key, $value, $attributes); - $text .= '
'; - $value = ""; - - // Appending needs is performed and customized using function: beforeUpdate($new_data, $old_data, $id) - } - - if(empty($parms['size'])) - { - $parms['size'] = 'xxlarge'; - } - - - $text .= vartrue($parms['pre']).$this->textarea($key, $value, vartrue($parms['rows'], 5), vartrue($parms['cols'], 40), vartrue($parms['__options'],$parms), varset($parms['counter'], false)).vartrue($parms['post']); - $ret = $text; - break; - - case 'bbarea': - $options = array('counter' => varset($parms['counter'], false)); - // Media = media-category owner used by media-manager. - $ret = vartrue($parms['pre']).$this->bbarea($key, $value, vartrue($parms['template']), vartrue($parms['media'],'_common_image'), vartrue($parms['size'], 'medium'),$options ).vartrue($parms['post']); - break; - - case 'video': - case 'image': //TODO - thumb, image list shortcode, js tooltip... - $label = varset($parms['label'], 'LAN_EDIT'); - - if(!empty($parms['optArray'])) - { - - return $this->imageradio($key,$value,$parms); - } - - - unset($parms['label']); - - if($attributes['type'] === 'video') - { - $parms['video'] = 2; // ie. video only. - $parms['w'] = 280; - } - - - $ret = $this->imagepicker($key, $value, defset($label, $label), $parms); - break; - - case 'images': - // return print_a($value, true); - $ret = ""; - $label = varset($parms['label'], 'LAN_EDIT'); - $max = varset($parms['max'],5); - - $ret .= "
"; - - for ($i=0; $i < $max; $i++) - { - $k = $key.'['.$i.'][path]'; - $ival = $value[$i]['path']; - - $ret .= $this->imagepicker($k, $ival, defset($label, $label), $parms); - } - - $ret .= "
"; - break; - - /** Generic Media Pick for combinations of images, audio, video, glyphs, files, etc. Field Type = json */ - case 'media': - - $max = varset($parms['max'],1); - - $ret = "
"; - for ($i=0; $i < $max; $i++) - { - $k = $key.'['.$i.'][path]'; - $ival = $value[$i]['path']; - - $ret .= $this->mediapicker($k, $ival, $parms); - } - - $ret .= "
"; - - return $ret; - break; - - case 'files': - - if($attributes['data'] == 'array') - { - $parms['data'] = 'array'; - } - - $ret = '
    '; - for ($i=0; $i < 5; $i++) - { - // $k = $key.'['.$i.'][path]'; - // $ival = $value[$i]['path']; - $k = $key.'['.$i.']'; - $ival = $value[$i]; - $ret .= '
  1. '.$this->filepicker($k, $ival, defset($label, $label), $parms).'
  2. '; - } - $ret .= '
'; - break; - - case 'file': //TODO - thumb, image list shortcode, js tooltip... - $label = varset($parms['label'], 'LAN_EDIT'); - unset($parms['label']); - $ret = $this->filepicker($key, $value, defset($label, $label), $parms); - break; - - case 'icon': - $label = varset($parms['label'], 'LAN_EDIT'); - $ajax = varset($parms['ajax'], true) ? true : false; - unset($parms['label'], $parms['ajax']); - $ret = $this->iconpicker($key, $value, defset($label, $label), $parms, $ajax); - break; - - case 'date': // date will show the datepicker but won't convert the value to unix. ie. string value will be saved. (or may be processed manually with beforeCreate() etc. Format may be determined by $parm. - case 'datestamp': - // If hidden, value is updated regardless. eg. a 'last updated' field. - // If not hidden, and there is a value, it is retained. eg. during the update of an existing record. - // otherwise it is added. eg. during the creation of a new record. - if(vartrue($parms['auto']) && (($value == null) || vartrue($parms['hidden']))) - { - $value = time(); - } - - if(vartrue($parms['readonly'])) // different to 'attribute-readonly' since the value may be auto-generated. - { - $ret = $this->renderValue($key, $value, $attributes).$this->hidden($key, $value); - } - elseif(vartrue($parms['hidden'])) - { - $ret = $this->hidden($key, $value); - } - else - { - $ret = $this->datepicker($key, $value, $parms); - } - break; - - case 'layouts': //to do - exclude param (exact match) - - $location = varset($parms['plugin']); // empty - core - $ilocation = vartrue($parms['id'], $location); // omit if same as plugin name - $where = vartrue($parms['area'], 'front'); //default is 'front' - $filter = varset($parms['filter']); - $merge = isset($parms['merge']) ? (bool) $parms['merge'] : true; - - $layouts = e107::getLayouts($location, $ilocation, $where, $filter, $merge, false); - - return vartrue($parms['pre'],'').$this->select($key, $layouts,$value,$parms).vartrue($parms['post'],''); - - /* if($tmp = e107::getTemplateInfo($location,$ilocation, null,true,$merge)) // read xxxx_INFO array from template file. - { - $opt = array(); - foreach($tmp as $k=>$inf) - { - $opt[$k] = $inf['title']; - } - - return vartrue($parms['pre'],'').$this->select($key,$opt,$value,$parms).vartrue($parms['post'],''); - }*/ - - - -/* - if(varset($parms['default']) && !isset($layouts[0]['default'])) - { - $layouts[0] = array('default' => $parms['default']) + $layouts[0]; - } - $info = array(); - if($layouts[1]) - { - foreach ($layouts[1] as $k => $info_array) - { - if(isset($info_array['description'])) - $info[$k] = defset($info_array['description'], $info_array['description']); - } - } - - */ - - //$this->selectbox($key, $layouts, $value) - // $ret = (vartrue($parms['raw']) ? $layouts[0] : $this->radio_multi($key, $layouts[0], $value,array('sep'=>"
"), $info)); - break; - - case 'templates': //to do - exclude param (exact match) - $templates = array(); - if(varset($parms['default'])) - { - $templates['default'] = defset($parms['default'], $parms['default']); - } - $location = vartrue($parms['plugin']) ? e_PLUGIN.$parms['plugin'].'/' : e_THEME; - $ilocation = vartrue($parms['location']); - $tmp = e107::getFile()->get_files($location.'templates/'.$ilocation, vartrue($parms['fmask'], '_template\.php$'), vartrue($parms['omit'], 'standard'), vartrue($parms['recurse_level'], 0)); - foreach(self::sort_get_files_output($tmp) as $files) - { - $k = str_replace('_template.php', '', $files['fname']); - $templates[$k] = implode(' ', array_map('ucfirst', explode('_', $k))); //TODO add LANS? - } - - // override - $where = vartrue($parms['area'], 'front'); - $location = vartrue($parms['plugin']) ? $parms['plugin'].'/' : ''; - $tmp = e107::getFile()->get_files(e107::getThemeInfo($where, 'rel').'templates/'.$location.$ilocation, vartrue($parms['fmask']), vartrue($parms['omit'], 'standard'), vartrue($parms['recurse_level'], 0)); - foreach(self::sort_get_files_output($tmp) as $files) - { - $k = str_replace('_template.php', '', $files['fname']); - $templates[$k] = implode(' ', array_map('ucfirst', explode('_', $k))); //TODO add LANS? - } - $ret = (vartrue($parms['raw']) ? $templates : $this->selectbox($key, $templates, $value)); - break; - - case 'checkboxes': - - if(is_array($parms)) - { - $eloptions = vartrue($parms['__options'], array()); - if(is_string($eloptions)) parse_str($eloptions, $eloptions); - if($attributes['type'] === 'comma') $eloptions['multiple'] = true; - unset($parms['__options']); - - if(!is_array($value) && !empty($value)) - { - $value = explode(",",$value); - } - - - $ret = vartrue($eloptions['pre']).$this->checkboxes($key, $parms, $value, $eloptions).vartrue($eloptions['post']); - - - } - return $ret; - break; - - - case 'dropdown': - case 'comma': - - - if(!empty($attributes['writeParms']['optArray'])) - { - $eloptions = $attributes['writeParms']; - unset($eloptions['optArray']); - } - else - { - $eloptions = vartrue($parms['__options'], array()); - } - - $value = (isset($eloptions['empty']) && ($value === null)) ? $eloptions['empty'] : $value; - - if(is_string($eloptions)) parse_str($eloptions, $eloptions); - if($attributes['type'] === 'comma') $eloptions['multiple'] = true; - unset($parms['__options']); - if(vartrue($eloptions['multiple']) && !is_array($value)) $value = explode(',', $value); - - // Allow Ajax API. - if(!empty($ajaxParms)) - { - $eloptions = array_merge_recursive($eloptions, $ajaxParms); - $eloptions['class'] = 'e-ajax ' . varset($eloptions['class']); - } - - $ret = vartrue($eloptions['pre']).$this->select($key, $parms, $value, $eloptions).vartrue($eloptions['post']); - break; - - case 'radio': - // TODO - more options (multi-line, help) - $eloptions = vartrue($parms['__options'], array()); - if(is_string($eloptions)) parse_str($eloptions, $eloptions); - unset($parms['__options']); - $ret = vartrue($eloptions['pre']).$this->radio_multi($key, $parms, $value, $eloptions, false).vartrue($eloptions['post']); - break; - - case 'userclass': - case 'userclasses': - - - $uc_options = vartrue($parms['classlist'], 'public,guest,nobody,member,admin,main,classes'); // defaults to 'public,guest,nobody,member,classes' (userclass handler) - unset($parms['classlist']); - - - // $method = ($attributes['type'] == 'userclass') ? 'uc_select' : 'uc_select'; - if(vartrue($attributes['type']) == 'userclasses'){ $parms['multiple'] = true; } - - $ret = vartrue($parms['pre']).$this->uc_select($key, $value, $uc_options, vartrue($parms, array())). vartrue($parms['post']); - break; - - /*case 'user_name': - case 'user_loginname': - case 'user_login': - case 'user_customtitle': - case 'user_email':*/ - case 'user': - //user_id expected - // Just temporary solution, could be changed soon - - - if(!isset($parms['__options'])) $parms['__options'] = array(); - if(!is_array($parms['__options'])) parse_str($parms['__options'], $parms['__options']); - - if((empty($value) || !empty($parms['currentInit']) && empty($parms['default']) ) || !empty($parms['current']) || (vartrue($parms['default']) == 'USERID')) // include current user by default. - { - $value = array('user_id'=>USERID, 'user_name'=>USERNAME); - if(vartrue($parms['current'])) - { - $parms['__options']['readonly'] = true; - } - - } - - - - - - // if(!is_array($value)) - // { - // $value = $value ? e107::getSystemUser($value, true)->getUserData() : array();// e107::user($value); - // } - - $colname = vartrue($parms['nameType'], 'user_name'); - $parms['__options']['name'] = $colname; - - // if(!$value) $value = array(); - // $uname = varset($value[$colname]); - // $value = varset($value['user_id'], 0); - - if(!empty($parms['limit'])) - { - $parms['__options']['limit'] = intval($parms['limit']); - } - - $ret = $this->userpicker(vartrue($parms['nameField'], $key), $value, vartrue($parms['__options'])); - - // $ret = $this->userpicker(vartrue($parms['nameField'], $key), $key, $uname, $value, vartrue($parms['__options'])); - break; - - - - - case 'bool': - case 'boolean': - - if(varset($parms['label']) === 'yesno') - { - $lenabled = 'LAN_YES'; - $ldisabled = 'LAN_NO'; - } - else - { - $lenabled = vartrue($parms['enabled'], 'LAN_ON'); - $ldisabled = (!empty($parms['disabled']) && is_string($parms['disabled'])) ? $parms['disabled'] : 'LAN_OFF'; - } - - unset($parms['enabled'], $parms['disabled'], $parms['label']); - $ret = vartrue($parms['pre']).$this->radio_switch($key, $value, defset($lenabled, $lenabled), defset($ldisabled, $ldisabled),$parms).vartrue($parms['post']); - break; - - case "checkbox": - - $value = (isset($parms['value'])) ? $parms['value'] : $value; - $ret = vartrue($parms['pre']).$this->checkbox($key, 1, $value,$parms).vartrue($parms['post']); - break; - - case 'method': // Custom Function - $meth = (!empty($attributes['method'])) ? $attributes['method'] : $key; - $parms['field'] = $key; - - if(strpos($meth,'::')!==false) - { - list($className,$meth) = explode('::', $meth); - $cls = new $className; - } - else - { - $cls = $this; - } - - $ret = call_user_func_array(array($cls, $meth), array($value, 'write', $parms)); - break; - - case 'upload': //TODO - from method - // TODO uploadfile SC is now processing uploads as well (add it to admin UI), write/readParms have to be added (see uploadfile.php parms) - $disbut = varset($parms['disable_button'], '0'); - $ret = $tp->parseTemplate("{UPLOADFILE=".(vartrue($parms['path']) ? e107::getParser()->replaceConstants($parms['path']) : e_UPLOAD)."|nowarn&trigger=etrigger_uploadfiles&disable_button={$disbut}}"); - break; - - case 'hidden': - - $value = (isset($parms['value'])) ? $parms['value'] : $value; - $ret = (vartrue($parms['show']) ? ($value ? $value : varset($parms['empty'], $value)) : ''); - $ret = $ret.$this->hidden($key, $value); - break; - - case 'lanlist': // installed languages - case 'language': // all languages - - $options = ($attributes['type'] === 'language') ? e107::getLanguage()->getList() : e107::getLanguage()->getLanSelectArray(); - - $eloptions = vartrue($parms['__options'], array()); - if(!is_array($eloptions)) parse_str($eloptions, $eloptions); - unset($parms['__options']); - if(vartrue($eloptions['multiple']) && !is_array($value)) $value = explode(',', $value); - $ret = vartrue($eloptions['pre']).$this->selectbox($key, $options, $value, $eloptions).vartrue($eloptions['post']); - break; - - case null: - // Possibly used in db but should not be submitted in form. @see news_extended. - break; - - default:// No LAN necessary, debug only. - $ret = (ADMIN) ? "".LAN_ERROR." Unknown 'type' : ".$attributes['type'] ."" : $value; - break; - } - - if(vartrue($parms['expand'])) - { - $k = "exp-".$this->name2id($key); - $text = "".$parms['expand'].""; - $text .= vartrue($parms['help']) ? '
'.$parms['help'].'
' : ''; - $text .= "
".$ret."
"; - return $text; - } - else - { - /** @deprecated usage @see renderCreateFieldset() should be attributes['help'] */ - $ret .= vartrue($parms['help']) ? '
'.$tp->toHTML($parms['help'],false,'defs').'
' : ''; - } - - return $ret; - } - - - private function imageradio($name,$value,$parms) - { - - if(!empty($parms['path'])) - { - $parms['legacy'] = $parms['path']; - } - - - $text = '
'; - - - - foreach($parms['optArray'] as $key=>$val) - { - $thumbnail = e107::getParser()->toImage($val,$parms); - - // $thumbnail = "".$val.""; - - - $selected = ($val == $value) ? " checked" : ""; - - $text .= " -
- -
"; - - } - - $text .= "
"; - - return $text; - - } - - - - /** - * Generic List Form, used internally by admin UI - * Expected options array format: - * - * 'myplugin', // unique string used for building element ids, REQUIRED - * 'pid' => 'primary_id', // primary field name, REQUIRED - * 'url' => '{e_PLUGIN}myplug/admin_config.php', // if not set, e_SELF is used - * 'query' => 'mode=main&action=list', // or e_QUERY if not set - * 'head_query' => 'mode=main&action=list', // without field, asc and from vars, REQUIRED - * 'np_query' => 'mode=main&action=list', // without from var, REQUIRED for next/prev functionality - * 'legend' => 'Fieldset Legend', // hidden by default - * 'form_pre' => '', // markup to be added before opening form element (e.g. Filter form) - * 'form_post' => '', // markup to be added after closing form element - * 'fields' => array(...), // see e_admin_ui::$fields - * 'fieldpref' => array(...), // see e_admin_ui::$fieldpref - * 'table_pre' => '', // markup to be added before opening table element - * 'table_post' => '', // markup to be added after closing table element (e.g. Batch actions) - * 'fieldset_pre' => '', // markup to be added before opening fieldset element - * 'fieldset_post' => '', // markup to be added after closing fieldset element - * 'perPage' => 15, // if 0 - no next/prev navigation - * 'from' => 0, // current page, default 0 - * 'field' => 'field_name', //current order field name, default - primary field - * 'asc' => 'desc', //current 'order by' rule, default 'asc' - * ); - * $tree_models['myplugin'] = new e_admin_tree_model($data); - * - * TODO - move fieldset & table generation in separate methods, needed for ajax calls - * @param array $form_options - * @param e_admin_tree_model $tree_model - * @param boolean $nocontainer don't enclose form in div container - * @return string - */ - public function renderListForm($form_options, $tree_models, $nocontainer = false) - { - $tp = e107::getParser(); - $text = ''; - - - // print_a($form_options); - - foreach ($form_options as $fid => $options) - { - /** @var e_tree_model $tree_model */ - $tree_model = $tree_models[$fid]; - $tree = $tree_model->getTree(); - $total = $tree_model->getTotal(); - - $amount = $options['perPage']; - $from = vartrue($options['from'], 0); - $field = vartrue($options['field'], $options['pid']); - $asc = strtoupper(vartrue($options['asc'], 'asc')); - $elid = $fid;//$options['id']; - $query = vartrue($options['query'],e_QUERY); // ? $options['query'] : ; - if(vartrue($_GET['action']) == 'list') - { - $query = e_QUERY; //XXX Quick fix for loss of pagination after 'delete'. - } - $url = (isset($options['url']) ? $tp->replaceConstants($options['url'], 'abs') : e_SELF); - $formurl = $url.($query ? '?'.$query : ''); - $fields = $options['fields']; - $current_fields = varset($options['fieldpref']) ? $options['fieldpref'] : array_keys($options['fields']); - $legend_class = vartrue($options['legend_class'], 'e-hideme'); - - - - $text .= " -
-
".$this->token()." - ".vartrue($options['fieldset_pre'])." -
- ".$options['legend']." - ".vartrue($options['table_pre'])." - - ".$this->colGroup($fields, $current_fields)." - ".$this->thead($fields, $current_fields, varset($options['head_query']), varset($options['query']))." - - "; - - if(!$tree) - { - $text .= " - -
"; - - $text .= "
".LAN_NO_RECORDS_FOUND."
"; // not prone to column-count issues. - } - else - { - /** @var e_model $model */ - foreach($tree as $model) - { - // $model->set('x_canonical_url', 'whatever'); - // var_dump($model); - e107::setRegistry('core/adminUI/currentListModel', $model); - $text .= $this->renderTableRow($fields, $current_fields, $model->getData(), $options['pid']); - } - - e107::setRegistry('core/adminUI/currentListModel', null); - - $text .= " - "; - } - - - $text .= vartrue($options['table_post']); - - - if($tree && $amount) - { - // New nextprev SC parameters - $parms = 'total='.$total; - $parms .= '&amount='.$amount; - $parms .= '¤t='.$from; - if(ADMIN_AREA) - { - $parms .= '&tmpl_prefix=admin'; - } - - // NOTE - the whole url is double encoded - reason is to not break parms query string - // 'np_query' should be proper (urlencode'd) url query string - $url = rawurlencode($url.'?'.(varset($options['np_query']) ? str_replace(array('&', '&'), array('&', '&'), $options['np_query']).'&' : '').'from=[FROM]'); - $parms .= '&url='.$url; - //$parms = $total.",".$amount.",".$from.",".$url.'?'.($options['np_query'] ? $options['np_query'].'&' : '').'from=[FROM]'; - //$text .= $tp->parseTemplate("{NEXTPREV={$parms}}"); - $nextprev = $tp->parseTemplate("{NEXTPREV={$parms}}"); - if ($nextprev) - { - $text .= "
".$nextprev."
"; - } - } - - $text .= " -
- ".vartrue($options['fieldset_post'])." -
-
- "; - } - if(!$nocontainer) - { - $text = '
'.$text.'
'; - } - return (vartrue($options['form_pre']).$text.vartrue($options['form_post'])); - } - - - /** - * Used with 'carousel' generates slides with X number of cells/blocks per slide. - * @param $cells - * @param int $perPage - * @return array - */ - private function slides($cells, $perPage=12) - { - $tmp = ''; - $s = 0; - $slides = array(); - foreach($cells as $cell) - { - $tmp .= $cell; - - $s++; - if($s == $perPage) - { - $slides[] = array('text'=>$tmp); - $tmp = ''; - $s = 0; - } - } - - if($s != $perPage && $s != 0) - { - $slides[] = array('text'=>$tmp); - } - - return $slides; - - - } - - - /** - * Render Grid-list layout. used internally by admin UI - * @param $form_options - * @param $tree_models - * @param bool|false $nocontainer - * @return string - */ - public function renderGridForm($form_options, $tree_models, $nocontainer = false) - { - $tp = e107::getParser(); - $text = ''; - - - // print_a($form_options); - - foreach ($form_options as $fid => $options) - { - $tree_model = $tree_models[$fid]; - $tree = $tree_model->getTree(); - $total = $tree_model->getTotal(); - - $amount = $options['perPage']; - $from = vartrue($options['from'], 0); - $field = vartrue($options['field'], $options['pid']); - $asc = strtoupper(vartrue($options['asc'], 'asc')); - $elid = $fid;//$options['id']; - $query = vartrue($options['query'],e_QUERY); // ? $options['query'] : ; - if(vartrue($_GET['action']) == 'list') - { - $query = e_QUERY; //XXX Quick fix for loss of pagination after 'delete'. - } - $url = (isset($options['url']) ? $tp->replaceConstants($options['url'], 'abs') : e_SELF); - $formurl = $url.($query ? '?'.$query : ''); - $fields = $options['fields']; - $current_fields = varset($options['fieldpref']) ? $options['fieldpref'] : array_keys($options['fields']); - $legend_class = vartrue($options['legend_class'], 'e-hideme'); - - - - $text .= " -
-
".$this->token()." - ".vartrue($options['fieldset_pre']); - - $text .= " - -
- ".$options['legend']." - ".vartrue($options['table_pre'])." -
- "; - - - if(!$tree) - { - $text .= "
"; - $text .= "
".LAN_NO_RECORDS_FOUND."
"; // not prone to column-count issues. - } - else - { - - - if(empty($options['grid']['template'])) - { - $template = '
-
{IMAGE} -
- {OPTIONS} -
-
- -
'; - } - else - { - $template = $options['grid']['template']; - } - - - $cls = !empty($options['grid']['class']) ? $options['grid']['class'] : 'col-md-2'; - $pid = $options['pid']; - $perPage = $options['grid']['perPage']; - - - - $gridFields = $options['grid']; - $gridFields['options'] = 'options'; - $gridFields['checkbox'] = 'checkboxes'; - - unset($gridFields['class'],$gridFields['perPage'], $gridFields['carousel']); - - $cells = array(); - foreach($tree as $model) - { - e107::setRegistry('core/adminUI/currentListModel', $model); - - $data = $model->getData(); - - $id = $data[$pid]; - $vars = array(); - - foreach($gridFields as $k=>$v) - { - $key = strtoupper($k); - $fields[$v]['grid'] = true; - $vars[$key] = $this->renderValue($v,$data[$v],$fields[$v],$id); - } - - $cells[] = "
". $tp->simpleParse($template,$vars). "
"; - - } - - - if($options['grid']['carousel'] === true) - { - $slides = $this->slides($cells, $perPage); - $carouselData = $this->carousel('admin-ui-carousel',$slides, array('wrap'=>false, 'interval'=>false, 'data'=>true)); - - $text .= $carouselData['start'].$carouselData['inner'].$carouselData['end']; - - } - else - { - $text .= implode("\n",$cells); - } - - - e107::setRegistry('core/adminUI/currentListModel', null); - - $text .= "
-
"; - } - - - $text .= vartrue($options['table_post']); - - - if($tree && $amount) - { - // New nextprev SC parameters - $parms = 'total='.$total; - $parms .= '&amount='.$amount; - $parms .= '¤t='.$from; - - if(ADMIN_AREA) - { - $parms .= '&tmpl_prefix=admin'; - } - - // NOTE - the whole url is double encoded - reason is to not break parms query string - // 'np_query' should be proper (urlencode'd) url query string - $url = rawurlencode($url.'?'.(varset($options['np_query']) ? str_replace(array('&', '&'), array('&', '&'), $options['np_query']).'&' : '').'from=[FROM]'); - $parms .= '&url='.$url; - //$parms = $total.",".$amount.",".$from.",".$url.'?'.($options['np_query'] ? $options['np_query'].'&' : '').'from=[FROM]'; - //$text .= $tp->parseTemplate("{NEXTPREV={$parms}}"); - $nextprev = $tp->parseTemplate("{NEXTPREV={$parms}}"); - if ($nextprev) - { - $text .= "
".$nextprev."
"; - } - } - - $text .= " - - ".vartrue($options['fieldset_post'])." -
- - "; - } - if(!$nocontainer) - { - $text = '
'.$text.'
'; - } - return (vartrue($options['form_pre']).$text.vartrue($options['form_post'])); - } - - /** - * Generic DB Record Management Form. - * TODO - lans - * TODO - move fieldset & table generation in separate methods, needed for ajax calls - * Expected arrays format: - * - * 'myplugin', - * 'url' => '{e_PLUGIN}myplug/admin_config.php', //if not set, e_SELF is used - * 'query' => 'mode=main&action=edit&id=1', //or e_QUERY if not set - * 'tabs' => true, * - * 'fieldsets' => array( - * 'general' => array( - * 'legend' => 'Fieldset Legend', - * 'fields' => array(...), //see e_admin_ui::$fields - * 'after_submit_options' => array('action' => 'Label'[,...]), // or true for default redirect options - * 'after_submit_default' => 'action_name', - * 'triggers' => 'auto', // standard create/update-cancel triggers - * //or custom trigger array in format array('sibmit' => array('Title', 'create', '1'), 'cancel') - trigger name - title, action, optional hidden value (in this case named sibmit_value) - * ), - * - * 'advanced' => array( - * 'legend' => 'Fieldset Legend', - * 'fields' => array(...), //see e_admin_ui::$fields - * 'after_submit_options' => array('__default' => 'action_name' 'action' => 'Label'[,...]), // or true for default redirect options - * 'triggers' => 'auto', // standard create/update-cancel triggers - * //or custom trigger array in format array('submit' => array('Title', 'create', '1'), 'cancel' => array('cancel', 'cancel')) - trigger name - title, action, optional hidden value (in this case named sibmit_value) - * ) - * ) - * ); - * $models[0] = new e_admin_model($data); - * $models[0]->setFieldIdName('primary_id'); // you need to do it if you don't use your own admin model extension - * - * @param array $forms numerical array - * @param array $models numerical array with values instance of e_admin_model - * @param boolean $nocontainer don't enclose in div container - * @return string - */ - function renderCreateForm($forms, $models, $nocontainer = false) - { - $text = ''; - foreach ($forms as $fid => $form) - { - $model = $models[$fid]; - - if(!is_object($model)) - { - e107::getDebug()->log("No model object found with key ".$fid); - } - - $query = isset($form['query']) ? $form['query'] : e_QUERY ; - $url = (isset($form['url']) ? e107::getParser()->replaceConstants($form['url'], 'abs') : e_SELF).($query ? '?'.$query : ''); - $curTab = strval(varset($_GET['tab'],'0')); - - $text .= " -
-
-
- ".vartrue($form['header'])." - ".$this->token()." - "; - - foreach ($form['fieldsets'] as $elid => $data) - { - $elid = $form['id'].'-'.$elid; - - - if(vartrue($data['tabs'])) // Tabs Present - { - $text .= '
'; - - foreach($data['tabs'] as $tabId=>$label) - { - $active = (strval($tabId) === $curTab) ? 'active' : ''; - $text .= '
'; - - // e107::getDebug()->log('elid: '.$elid. " tabid: ".$tabId); - // e107::getDebug()->log($data); - // e107::getDebug()->log($model); - - - $text .= $this->renderCreateFieldset($elid, $data, $model, $tabId); - $text .= "
"; - } - - $text .= "
"; - $text .= $this->renderCreateButtonsBar($elid, $data, $model, $tabId); // Create/Update Buttons etc. - - } - else // No Tabs Present - { - $text .= $this->renderCreateFieldset($elid, $data, $model, false); - $text .= $this->renderCreateButtonsBar($elid, $data, $model, false); // Create/Update Buttons etc. - } - - - } - - $text .= " - ".vartrue($form['footer'])." -
-
- "; - - // e107::js('footer-inline',"Form.focusFirstElement('{$form['id']}-form');",'prototype'); - // e107::getJs()->footerInline("Form.focusFirstElement('{$form['id']}-form');"); - } - if(!$nocontainer) - { - $text = '
'.$text.'
'; - } - return $text; - } - - /** - * Create form fieldset, called internal by {@link renderCreateForm()) - * - * @param string $id field id - * @param array $fdata fieldset data - * @param object $model - * @return string | false - */ - function renderCreateFieldset($id, $fdata, $model, $tab=0) - { - - - $start = vartrue($fdata['fieldset_pre'])." -
- ".vartrue($fdata['legend'])." - ".vartrue($fdata['table_pre'])." - - - - - - - "; - - $text = ''; - - // required fields - model definition - $model_required = $model->getValidationRules(); - $required_help = false; - $hidden_fields = array(); - - foreach($fdata['fields'] as $key => $att) - { - if($tab !== false && varset($att['tab'], 0) !== $tab) - { - continue; - } - - // convert aliases - not supported in edit mod - if(vartrue($att['alias']) && !$model->hasData($key)) - { - $key = $att['field']; - } - - if($key == 'checkboxes' || $key == 'options' || ($att['type'] === null) || ($att['type'] === false)) - { - continue; - } - - $parms = vartrue($att['formparms'], array()); - if(!is_array($parms)) parse_str($parms, $parms); - $label = !empty($att['note']) ? '
'.deftrue($att['note'], $att['note']).'
' : ''; - $help = !empty($att['help']) ? '
'.deftrue($att['help'], $att['help']).'
' : ''; - - - $valPath = trim(vartrue($att['dataPath'], $key), '/'); - $keyName = $key; - if(strpos($valPath, '/')) //not TRUE, cause string doesn't start with / - { - $tmp = explode('/', $valPath); - $keyName = array_shift($tmp); - foreach ($tmp as $path) - { - $keyName .= '['.$path.']'; - } - } - - if(!empty($att['writeParms']) && !is_array($att['writeParms'])) - { - parse_str(varset($att['writeParms']), $writeParms); - } - else - { - $writeParms = varset($att['writeParms']); - } - - if(!empty($writeParms['sef'])) // group sef generate button with input element. - { - if(empty($writeParms['tdClassRight'])) - { - $writeParms['tdClassRight'] = 'input-group'; - - } - else - { - $writeParms['tdClassRight'] .= ' input-group'; - } - - } - - if('hidden' === $att['type']) - { - - if(empty($writeParms['show'])) - { - $hidden_fields[] = $this->renderElement($keyName, $model->getIfPosted($valPath), $att, varset($model_required[$key], array())); - - continue; - } - unset($tmp); - } - - // type null - system (special) fields - if(vartrue($att['type']) !== null && !vartrue($att['noedit']) && $key != $model->getFieldIdName()) - { - $required = ''; - $required_class = ''; - if(isset($model_required[$key]) || vartrue($att['validate']) || !empty($att['writeParms']['required'])) - { - - $required = $this->getRequiredString(); - $required_class = ' class="required-label" title="'.LAN_REQUIRED.'"'; - $required_help = true; - - if(!empty($att['validate'])) - { - // override - $model_required[$key] = array(); - $model_required[$key][] = true === $att['validate'] ? 'required' : $att['validate']; - $model_required[$key][] = varset($att['rule']); - $model_required[$key][] = $att['title']; - $model_required[$key][] = varset($att['error']); - } - } - - /* - if('hidden' === $att['type']) - { - parse_str(varset($att['writeParms']), $tmp); - if(!vartrue($tmp['show'])) - { - $hidden_fields[] = $this->renderElement($keyName, $model->getIfPosted($valPath), $att, varset($model_required[$key], array())); - unset($tmp); - continue; - } - unset($tmp); - } - */ - - if(in_array($key,$this->_field_warnings)) - { - if(is_string($writeParms)) - { - parse_str($writeParms,$writeParms); - } - - $writeParms['tdClassRight'] .= ' has-warning'; - - } - - $leftCell = "".defset(vartrue($att['title']), vartrue($att['title']))."".$required.$label; - $rightCell = $this->renderElement($keyName, $model->getIfPosted($valPath), $att, varset($model_required[$key], array()), $model->getId())." ".$help; - - if(vartrue($att['type']) == 'bbarea' || !empty($writeParms['nolabel'])) - { - $text .= " - - - - "; - - } - else - { -// rightCellClass - // leftCellClass - $leftCellClass = (!empty($writeParms['tdClassLeft'])) ? " class='".$writeParms['tdClassLeft']."'" : ""; - $rightCellClass = (!empty($writeParms['tdClassRight'])) ? " class='".$writeParms['tdClassRight']."'" : ""; - $trClass = (!empty($writeParms['trClass'])) ? " class='".$writeParms['trClass']."'" : ""; - - $text .= " - - - ".$leftCell." - - - ".$rightCell." - - - "; - } - - - - - - } - //if($bckp) $model->remove($bckp); - - } - - //print_a($fdata); - - if($required_help) - { - $required_help = '
'.$this->getRequiredString().' - required fields
'; //TODO - lans - } - - - if(!empty($text) || !empty($hidden_fields)) - { - $text = $start.$text; - - $text .= " -
-
"; - - $text .= (isset($writeParms['nolabel']) && $writeParms['nolabel'] == 2) ? '' : "
".$leftCell."
" ; - $text .= $rightCell." -
"; - - $text .= implode("\n", $hidden_fields); - - $text .= "
"; - - $text .= vartrue($fdata['fieldset_post']); - - return $text; - } - - - - return false; - - /* - $text .= " - ".implode("\n", $hidden_fields)." - ".$required_help." - ".vartrue($fdata['table_post'])." -
- "; - // After submit options - $defsubmitopt = array('list' => 'go to list', 'create' => 'create another', 'edit' => 'edit current'); - $submitopt = isset($fdata['after_submit_options']) ? $fdata['after_submit_options'] : true; - if(true === $submitopt) - { - $submitopt = $defsubmitopt; - } - - if($submitopt) - { - $selected = isset($fdata['after_submit_default']) && array_key_exists($fdata['after_submit_default'], $submitopt) ? $fdata['after_submit_default'] : ''; - - } - - $triggers = vartrue($fdata['triggers'], 'auto'); - if(is_string($triggers) && 'auto' === $triggers) - { - $triggers = array(); - if($model->getId()) - { - $triggers['submit'] = array(LAN_UPDATE, 'update', $model->getId()); - } - else - { - $triggers['submit'] = array(LAN_CREATE, 'create', 0); - } - $triggers['cancel'] = array(LAN_CANCEL, 'cancel'); - } - - foreach ($triggers as $trigger => $tdata) - { - $text .= ($trigger == 'submit') ? "
" : ""; - $text .= $this->admin_button('etrigger_'.$trigger, $tdata[0], $tdata[1]); - - if($trigger == 'submit' && $submitopt) - { - - $text .= - ' - '; - } - - $text .= ($trigger == 'submit') ?"
" : ""; - - if(isset($tdata[2])) - { - $text .= $this->hidden($trigger.'_value', $tdata[2]); - } - } - - $text .= " -
- - ".vartrue($fdata['fieldset_post'])." - "; - return $text; - */ - } - - - function renderCreateButtonsBar($id, $fdata, $model, $tab=0) - { - /* - $text = vartrue($fdata['fieldset_pre'])." -
- ".vartrue($fdata['legend'])." - ".vartrue($fdata['table_pre'])." - - - - - - - "; - */ - $text = ''; - - // required fields - model definition - $model_required = $model->getValidationRules(); - $required_help = false; - $hidden_fields = array(); - foreach($fdata['fields'] as $key => $att) - { - - if($tab !== false && varset($att['tab'], 0) !== $tab) - { - continue; - } - - // convert aliases - not supported in edit mod - if(vartrue($att['alias']) && !$model->hasData($key)) - { - $key = $att['field']; - } - - if($key == 'checkboxes' || $key == 'options') - { - continue; - } - - $parms = vartrue($att['formparms'], array()); - if(!is_array($parms)) parse_str($parms, $parms); - $label = vartrue($att['note']) ? '
'.deftrue($att['note'], $att['note']).'
' : ''; - $help = vartrue($att['help']) ? '
'.deftrue($att['help'], $att['help']).'
' : ''; - - $valPath = trim(vartrue($att['dataPath'], $key), '/'); - $keyName = $key; - if(strpos($valPath, '/')) //not TRUE, cause string doesn't start with / - { - $tmp = explode('/', $valPath); - $keyName = array_shift($tmp); - foreach ($tmp as $path) - { - $keyName .= '['.$path.']'; - } - } - - if('hidden' === $att['type']) - { - if(!is_array($att['writeParms'])) parse_str(varset($att['writeParms']), $tmp); - else $tmp = $att['writeParms']; - - if(!vartrue($tmp['show'])) - { - $hidden_fields[] = $this->renderElement($keyName, $model->getIfPosted($valPath), $att, varset($model_required[$key], array()), $model->getId()); - unset($tmp); - continue; - } - unset($tmp); - } - - // type null - system (special) fields - if(vartrue($att['type']) !== null && !vartrue($att['noedit']) && $key != $model->getFieldIdName()) - { - $required = ''; - $required_class = ''; - if(isset($model_required[$key]) || vartrue($att['validate'])) - { - $required = $this->getRequiredString(); - $required_class = ' class="required-label"'; // TODO - add 'required-label' to the core CSS definitions - $required_help = true; - if(vartrue($att['validate'])) - { - // override - $model_required[$key] = array(); - $model_required[$key][] = true === $att['validate'] ? 'required' : $att['validate']; - $model_required[$key][] = varset($att['rule']); - $model_required[$key][] = $att['title']; - $model_required[$key][] = varset($att['error']); - } - } - - /* - $text .= " - - - - - "; - * */ - } - //if($bckp) $model->remove($bckp); - - } - - if($required_help) - { - // $required_help = '
'.$this->getRequiredString().' - required fields
'; //TODO - lans - } - - // $text .= " - // - //
- ".$required."".defset(vartrue($att['title']), vartrue($att['title']))."".$label." - - ".$this->renderElement($keyName, $model->getIfPosted($valPath), $att, varset($model_required[$key], array()))." - {$help} -
"; - - - - $text .= " - ".implode("\n", $hidden_fields)." - ".vartrue($fdata['table_post'])." -
- "; - // After submit options - $defsubmitopt = array('list' => LAN_EFORM_013, 'create' => LAN_EFORM_014, 'edit' => LAN_EFORM_015); - $submitopt = isset($fdata['after_submit_options']) ? $fdata['after_submit_options'] : true; - - if(true === $submitopt) - { - $submitopt = $defsubmitopt; - } - - if($submitopt) - { - $selected = isset($fdata['after_submit_default']) && array_key_exists($fdata['after_submit_default'], $submitopt) ? $fdata['after_submit_default'] : 'list'; - } - - $triggers = (empty($fdata['triggers']) && $fdata['triggers'] !== false) ? 'auto' : $fdata['triggers']; // vartrue($fdata['triggers'], 'auto'); - if(is_string($triggers) && 'auto' === $triggers) - { - $triggers = array(); - if($model->getId()) - { - $triggers['submit'] = array(LAN_UPDATE, 'update', $model->getId()); - } - else - { - $triggers['submit'] = array(LAN_CREATE, 'create', 0); - } - $triggers['cancel'] = array(LAN_CANCEL, 'cancel'); - } - - if(!empty($triggers)) - { - foreach ($triggers as $trigger => $tdata) - { - $text .= ($trigger == 'submit') ? "
" : ""; - $text .= $this->admin_button('etrigger_'.$trigger, $tdata[1], $tdata[1], $tdata[0]); - - if($trigger == 'submit' && $submitopt) - { - - $text .= - ' - '; - } - - $text .= ($trigger == 'submit') ?"
" : ""; - - if(isset($tdata[2])) - { - $text .= $this->hidden($trigger.'_value', $tdata[2]); - } - } - } - - $text .= " -
- - ".vartrue($fdata['fieldset_post'])." - "; - return $text; - } - - - /** - * Generic renderForm solution - * @param @forms - * @param @nocontainer - * @return string - */ - function renderForm($forms, $nocontainer = false) - { - $text = ''; - foreach ($forms as $fid => $form) - { - $query = isset($form['query']) ? $form['query'] : e_QUERY ; - $url = (isset($form['url']) ? e107::getParser()->replaceConstants($form['url'], 'abs') : e_SELF).($query ? '?'.$query : ''); - - $text .= " - ".vartrue($form['form_pre'])." -
-
- ".vartrue($form['header'])." - ".$this->token()." - "; - - foreach ($form['fieldsets'] as $elid => $fieldset_data) - { - $elid = $form['id'].'-'.$elid; - $text .= $this->renderFieldset($elid, $fieldset_data); - } - - $text .= " - ".vartrue($form['footer'])." -
-
- ".vartrue($form['form_post'])." - "; - } - if(!$nocontainer) - { - $text = '
'.$text.'
'; - } - return $text; - } - - /** - * Generic renderFieldset solution, will be split to renderTable, renderCol/Row/Box etc - Still in use. - */ - function renderFieldset($id, $fdata) - { - $colgroup = ''; - if(vartrue($fdata['table_colgroup'])) - { - $colgroup = " - - "; - foreach ($fdata['table_colgroup'] as $i => $colgr) - { - $colgroup .= " $v) - { - $colgroup .= "{$attr}='{$v}'"; - } - $colgroup .= " /> - "; - } - - $colgroup = " - "; - } - $text = vartrue($fdata['fieldset_pre'])." -
- ".vartrue($fdata['legend'])." - ".vartrue($fdata['table_pre'])." - - "; - - if(vartrue($fdata['table_rows']) || vartrue($fdata['table_body'])) - { - $text .= " - - {$colgroup} - - ".vartrue($fdata['table_head'])." - - - "; - - if(vartrue($fdata['table_rows'])) - { - foreach($fdata['table_rows'] as $index => $row) - { - $text .= " - - $row - - "; - } - } - elseif(vartrue($fdata['table_body'])) - { - $text .= $fdata['table_body']; - } - - if(vartrue($fdata['table_note'])) - { - $note = '
'.$fdata['table_note'].'
'; - } - - $text .= " - -
- ".$note." - ".vartrue($fdata['table_post'])." - "; - } - - $triggers = vartrue($fdata['triggers'], array()); - if($triggers) - { - $text .= "
- ".vartrue($fdata['pre_triggers'], '')." - "; - foreach ($triggers as $trigger => $tdata) - { - if(is_string($tdata)) - { - $text .= $tdata; - continue; - } - $text .= $this->admin_button('etrigger_'.$trigger, $tdata[0], $tdata[1]); - if(isset($tdata[2])) - { - $text .= $this->hidden($trigger.'_value', $tdata[2]); - } - } - $text .= "
"; - } - - $text .= " -
- ".vartrue($fdata['fieldset_post'])." - "; - return $text; - } - - /** - * Render Value Trigger - override to modify field/value/parameters - * @param string $field field name - * @param mixed $value field value - * @param array $params 'writeParams' key (see $controller->fields array) - * @param int $id record ID - */ - public function renderValueTrigger(&$field, &$value, &$params, $id) - { - - } - - /** - * Render Element Trigger - override to modify field/value/parameters/validation data - * @param string $field field name - * @param mixed $value field value - * @param array $params 'writeParams' key (see $controller->fields array) - * @param array $required_data validation data - * @param int $id record ID - */ - public function renderElementTrigger(&$field, &$value, &$params, &$required_data, $id) - { - - } -} - -// DEPRECATED - use above methods instead ($frm) -class form -{ - function form_open($form_method, $form_action, $form_name = "", $form_target = "", $form_enctype = "", $form_js = "") - { - $method = ($form_method ? "method='".$form_method."'" : ""); - $target = ($form_target ? " target='".$form_target."'" : ""); - $name = ($form_name ? " id='".$form_name."' " : " id='myform'"); - return "\n
".e107::getForm()->token()."
"; - } - - function form_text($form_name, $form_size, $form_value, $form_maxlength = FALSE, $form_class = "tbox form-control", $form_readonly = "", $form_tooltip = "", $form_js = "") { - $name = ($form_name ? " id='".$form_name."' name='".$form_name."'" : ""); - $value = (isset($form_value) ? " value='".$form_value."'" : ""); - $size = ($form_size ? " size='".$form_size."'" : ""); - $maxlength = ($form_maxlength ? " maxlength='".$form_maxlength."'" : ""); - $readonly = ($form_readonly ? " readonly='readonly'" : ""); - $tooltip = ($form_tooltip ? " title='".$form_tooltip."'" : ""); - return "\n"; - } - - function form_password($form_name, $form_size, $form_value, $form_maxlength = FALSE, $form_class = "tbox form-control", $form_readonly = "", $form_tooltip = "", $form_js = "") { - $name = ($form_name ? " id='".$form_name."' name='".$form_name."'" : ""); - $value = (isset($form_value) ? " value='".$form_value."'" : ""); - $size = ($form_size ? " size='".$form_size."'" : ""); - $maxlength = ($form_maxlength ? " maxlength='".$form_maxlength."'" : ""); - $readonly = ($form_readonly ? " readonly='readonly'" : ""); - $tooltip = ($form_tooltip ? " title='".$form_tooltip."'" : ""); - return "\n"; - } - - function form_button($form_type, $form_name, $form_value, $form_js = "", $form_image = "", $form_tooltip = "") { - $name = ($form_name ? " id='".$form_name."' name='".$form_name."'" : ""); - $image = ($form_image ? " src='".$form_image."' " : ""); - $tooltip = ($form_tooltip ? " title='".$form_tooltip."' " : ""); - return "\n"; - } - - function form_textarea($form_name, $form_columns, $form_rows, $form_value, $form_js = "", $form_style = "", $form_wrap = "", $form_readonly = "", $form_tooltip = "") { - $name = ($form_name ? " id='".$form_name."' name='".$form_name."'" : ""); - $readonly = ($form_readonly ? " readonly='readonly'" : ""); - $tooltip = ($form_tooltip ? " title='".$form_tooltip."'" : ""); - $wrap = ($form_wrap ? " wrap='".$form_wrap."'" : ""); - $style = ($form_style ? " style='".$form_style."'" : ""); - return "\n"; - } - - function form_checkbox($form_name, $form_value, $form_checked = 0, $form_tooltip = "", $form_js = "") { - $name = ($form_name ? " id='".$form_name.$form_value."' name='".$form_name."'" : ""); - $checked = ($form_checked ? " checked='checked'" : ""); - $tooltip = ($form_tooltip ? " title='".$form_tooltip."'" : ""); - return "\n"; - - } - - function form_radio($form_name, $form_value, $form_checked = 0, $form_tooltip = "", $form_js = "") { - $name = ($form_name ? " id='".$form_name.$form_value."' name='".$form_name."'" : ""); - $checked = ($form_checked ? " checked='checked'" : ""); - $tooltip = ($form_tooltip ? " title='".$form_tooltip."'" : ""); - return "\n"; - - } - - function form_file($form_name, $form_size, $form_tooltip = "", $form_js = "") { - $name = ($form_name ? " id='".$form_name."' name='".$form_name."'" : ""); - $tooltip = ($form_tooltip ? " title='".$form_tooltip."'" : ""); - return ""; - } - - function form_select_open($form_name, $form_js = "") { - return "\n"; - } - - function form_option($form_option, $form_selected = "", $form_value = "", $form_js = "") { - $value = ($form_value !== FALSE ? " value='".$form_value."'" : ""); - $selected = ($form_selected ? " selected='selected'" : ""); - return "\n".$form_option.""; - } - - function form_hidden($form_name, $form_value) { - return "\n"; - } - - function form_close() { - return "\n"; - } -} - -/* -Usage -echo $rs->form_open("post", e_SELF, "_blank"); -echo $rs->form_text("testname", 100, "this is the value", 100, 0, "tooltip"); -echo $rs->form_button("submit", "testsubmit", "SUBMIT!", "", "Click to submit"); -echo $rs->form_button("reset", "testreset", "RESET!", "", "Click to reset"); -echo $rs->form_textarea("textareaname", 10, 10, "Value", "overflow:hidden"); -echo $rs->form_checkbox("testcheckbox", 1, 1); -echo $rs->form_checkbox("testcheckbox2", 2); -echo $rs->form_hidden("hiddenname", "hiddenvalue"); -echo $rs->form_radio("testcheckbox", 1, 1); -echo $rs->form_radio("testcheckbox", 1); -echo $rs->form_file("testfile", "20"); -echo $rs->form_select_open("testselect"); -echo $rs->form_option("Option 1"); -echo $rs->form_option("Option 2"); -echo $rs->form_option("Option 3", 1, "defaultvalue"); -echo $rs->form_option("Option 4"); -echo $rs->form_select_close(); -echo $rs->form_close(); -*/ - - -?> + (mixed) custom id attribute value + * if numeric value is passed it'll be just appended to the name e.g. {filed-name}-{value} + * if false is passed id will be not created + * if empty string is passed (or no 'id' option is found) + * in all other cases the value will be used as field id + * default: empty string + * + * - class => (string) field class(es) + * Example: 'tbox select class1 class2 class3' + * NOTE: this will override core classes, so you have to explicit include them! + * default: empty string + * + * - size => (int) size attribute value (used when needed) + * default: 40 + * + * - title (string) title attribute + * default: empty string (omitted) + * + * - readonly => (bool) readonly attribute + * default: false + * + * - selected => (bool) selected attribute (used when needed) + * default: false + * + * checked => (bool) checked attribute (used when needed) + * default: false + * - disabled => (bool) disabled attribute + * default: false + * + * - tabindex => (int) tabindex attribute value + * default: inner tabindex counter + * + * - other => (string) additional data + * Example: 'attribute1="value1" attribute2="value2"' + * default: empty string + */ +class e_form +{ + protected $_tabindex_counter = 0; + protected $_tabindex_enabled = true; + protected $_cached_attributes = array(); + protected $_field_warnings = array(); + private $_inline_token = null; + + /** + * @var user_class + */ + protected $_uc; + + protected $_required_string; + + function __construct($enable_tabindex = false) + { + e107_include_once(e_LANGUAGEDIR.e_LANGUAGE."/lan_form_handler.php"); + $this->_tabindex_enabled = $enable_tabindex; + $this->_uc = e107::getUserClass(); + $this->setRequiredString(' *'); + } + + /** + * @return array + * @see https://github.com/e107inc/e107/issues/3533 + */ + private static function sort_get_files_output($tmp) + { + usort($tmp, function ($left, $right) { + $left_full_path = $left['path'] . $left['fname']; + $right_full_path = $right['path'] . $right['fname']; + return strcmp($left_full_path, $right_full_path); + }); + return $tmp; + } + + + public function addWarning($field) + { + $this->_field_warnings[] = $field; + + } + + /** + * Open a new form + * @param string name + * @param $method - post|get default is post + * @param @target - e_REQUEST_URI by default + * @param $other - unused at the moment. + * @return string + */ + public function open($name, $method=null, $target=null, $options=null) + { + if($target == null) + { + $target = e_REQUEST_URI; + } + + if($method == null) + { + $method = "post"; + } + + $class = ""; + $autoComplete = ""; + + if(is_string($options)) + { + parse_str($options, $options); + } + + if(vartrue($options['class'])) + { + $class = "class='".$options['class']."'"; + } + else // default + { + $class= "class='form-horizontal'"; + } + + if(isset($options['autocomplete'])) // leave as isset() + { + $autoComplete = " autocomplete='".($options['autocomplete'] ? 'on' : 'off')."'"; + } + + + if($method == 'get' && strpos($target,'=')) + { + list($url,$qry) = explode("?",$target); + $text = "\n
\n"; + + parse_str($qry,$m); + foreach($m as $k=>$v) + { + $text .= $this->hidden($k, $v); + } + + } + else + { + $target = str_replace("&", "&", $target); + $text = "\n\n"; + } + return $text; + } + + /** + * Close a Form + */ + public function close() + { + return "
"; + + } + + + /** + * Render a country drop-down list. + * @param string $name + * @param string $value + * @param array $options + * @return string + */ + public function country($name, $value, $options=array()) + { + + $arr = $this->getCountry(); + + $placeholder = isset($options['placeholder']) ? $options['placeholder'] : ' '; + + return $this->select($name, $arr, $value, $options, $placeholder); + } + + + /** + * Get a list of countries. + * @param null|string $iso ISO code. + * @return array|mixed|string + */ + public function getCountry($iso=null) // move to parser? + { + + $c = array(); + + $c['af'] = "Afghanistan"; + $c['al'] = "Albania"; + $c['dz'] = "Algeria"; + $c['as'] = "American Samoa"; + $c['ad'] = "Andorra"; + $c['ao'] = "Angola"; + $c['ai'] = "Anguilla"; + $c['aq'] = "Antarctica"; + $c['ag'] = "Antigua and Barbuda"; + $c['ar'] = "Argentina"; + $c['am'] = "Armenia"; + $c['aw'] = "Aruba"; + $c['au'] = "Australia"; + $c['at'] = "Austria"; + $c['az'] = "Azerbaijan"; + $c['bs'] = "Bahamas"; + $c['bh'] = "Bahrain"; + $c['bd'] = "Bangladesh"; + $c['bb'] = "Barbados"; + $c['by'] = "Belarus"; + $c['be'] = "Belgium"; + $c['bz'] = "Belize"; + $c['bj'] = "Benin"; + $c['bm'] = "Bermuda"; + $c['bt'] = "Bhutan"; + $c['bo'] = "Bolivia"; + $c['ba'] = "Bosnia-Herzegovina"; + $c['bw'] = "Botswana"; + $c['bv'] = "Bouvet Island"; + $c['br'] = "Brazil"; + $c['io'] = "British Indian Ocean Territory"; + $c['bn'] = "Brunei Darussalam"; + $c['bg'] = "Bulgaria"; + $c['bf'] = "Burkina Faso"; + $c['bi'] = "Burundi"; + $c['kh'] = "Cambodia"; + $c['cm'] = "Cameroon"; + $c['ca'] = "Canada"; + + $c['cv'] = "Cape Verde"; + $c['ky'] = "Cayman Islands"; + $c['cf'] = "Central African Republic"; + $c['td'] = "Chad"; + $c['cl'] = "Chile"; + $c['cn'] = "China"; + $c['cx'] = "Christmas Island"; + $c['cc'] = "Cocos (Keeling) Islands"; + $c['co'] = "Colombia"; + $c['km'] = "Comoros"; + $c['cg'] = "Congo"; + $c['cd'] = "Congo (Dem.Rep)"; + $c['ck'] = "Cook Islands"; + $c['cr'] = "Costa Rica"; + $c['hr'] = "Croatia"; + $c['cu'] = "Cuba"; + $c['cy'] = "Cyprus"; + $c['cz'] = "Czech Republic"; + $c['dk'] = "Denmark"; + $c['dj'] = "Djibouti"; + $c['dm'] = "Dominica"; + $c['do'] = "Dominican Republic"; + $c['tp'] = "East Timor"; + $c['ec'] = "Ecuador"; + $c['eg'] = "Egypt"; + $c['sv'] = "El Salvador"; + $c['gq'] = "Equatorial Guinea"; + $c['er'] = "Eritrea"; + $c['ee'] = "Estonia"; + $c['et'] = "Ethiopia"; + $c['fk'] = "Falkland Islands"; + $c['fo'] = "Faroe Islands"; + $c['fj'] = "Fiji"; + $c['fi'] = "Finland"; + // $c['cs'] = "Former Czechoslovakia"; + // $c['su'] = "Former USSR"; + $c['fr'] = "France"; + // $c['fx'] = "France (European Territory)"; + $c['gf'] = "French Guyana"; + $c['tf'] = "French Southern Territories"; + $c['ga'] = "Gabon"; + $c['gm'] = "Gambia"; + $c['ge'] = "Georgia"; + $c['de'] = "Germany"; + $c['gh'] = "Ghana"; + $c['gi'] = "Gibraltar"; + $c['gr'] = "Greece"; + $c['gl'] = "Greenland"; + $c['gd'] = "Grenada"; + $c['gp'] = "Guadeloupe (French)"; + $c['gu'] = "Guam (USA)"; + $c['gt'] = "Guatemala"; + $c['gn'] = "Guinea"; + $c['gw'] = "Guinea Bissau"; + $c['gy'] = "Guyana"; + $c['ht'] = "Haiti"; + $c['hm'] = "Heard and McDonald Islands"; + $c['hn'] = "Honduras"; + $c['hk'] = "Hong Kong"; + $c['hu'] = "Hungary"; + $c['is'] = "Iceland"; + $c['in'] = "India"; + $c['id'] = "Indonesia"; + $c['ir'] = "Iran"; + $c['iq'] = "Iraq"; + $c['ie'] = "Ireland"; + $c['il'] = "Israel"; + $c['it'] = "Italy"; + $c['ci'] = "Ivory Coast (Cote D'Ivoire)"; + $c['jm'] = "Jamaica"; + $c['jp'] = "Japan"; + $c['jo'] = "Jordan"; + $c['kz'] = "Kazakhstan"; + $c['ke'] = "Kenya"; + $c['ki'] = "Kiribati"; + $c['kp'] = "Korea (North)"; + $c['kr'] = "Korea (South)"; + $c['kw'] = "Kuwait"; + $c['kg'] = "Kyrgyzstan"; + $c['la'] = "Laos"; + $c['lv'] = "Latvia"; + $c['lb'] = "Lebanon"; + $c['ls'] = "Lesotho"; + $c['lr'] = "Liberia"; + $c['ly'] = "Libya"; + $c['li'] = "Liechtenstein"; + $c['lt'] = "Lithuania"; + $c['lu'] = "Luxembourg"; + $c['mo'] = "Macau"; + $c['mk'] = "Macedonia"; + $c['mg'] = "Madagascar"; + $c['mw'] = "Malawi"; + $c['my'] = "Malaysia"; + $c['mv'] = "Maldives"; + $c['ml'] = "Mali"; + $c['mt'] = "Malta"; + $c['mh'] = "Marshall Islands"; + $c['mq'] = "Martinique (French)"; + $c['mr'] = "Mauritania"; + $c['mu'] = "Mauritius"; + $c['yt'] = "Mayotte"; + $c['mx'] = "Mexico"; + $c['fm'] = "Micronesia"; + $c['md'] = "Moldavia"; + $c['mc'] = "Monaco"; + $c['mn'] = "Mongolia"; + $c['me'] = "Montenegro"; + $c['ms'] = "Montserrat"; + $c['ma'] = "Morocco"; + $c['mz'] = "Mozambique"; + $c['mm'] = "Myanmar"; + $c['na'] = "Namibia"; + $c['nr'] = "Nauru"; + $c['np'] = "Nepal"; + $c['nl'] = "Netherlands"; + $c['an'] = "Netherlands Antilles"; + // $c['net'] = "Network"; + + $c['nc'] = "New Caledonia (French)"; + $c['nz'] = "New Zealand"; + $c['ni'] = "Nicaragua"; + $c['ne'] = "Niger"; + $c['ng'] = "Nigeria"; + $c['nu'] = "Niue"; + $c['nf'] = "Norfolk Island"; + + $c['mp'] = "Northern Mariana Islands"; + $c['no'] = "Norway"; + // $c['arpa'] = "Old style Arpanet"; + $c['om'] = "Oman"; + $c['pk'] = "Pakistan"; + $c['pw'] = "Palau"; + $c['pa'] = "Panama"; + $c['pg'] = "Papua New Guinea"; + $c['py'] = "Paraguay"; + $c['pe'] = "Peru"; + $c['ph'] = "Philippines"; + $c['pn'] = "Pitcairn Island"; + $c['pl'] = "Poland"; + $c['pf'] = "Polynesia (French)"; + $c['pt'] = "Portugal"; + $c['pr'] = "Puerto Rico"; + $c['ps'] = "Palestine"; + $c['qa'] = "Qatar"; + $c['re'] = "Reunion (French)"; + $c['ro'] = "Romania"; + $c['ru'] = "Russia"; + $c['rw'] = "Rwanda"; + $c['gs'] = "S. Georgia & S. Sandwich Isls."; + $c['sh'] = "Saint Helena"; + $c['kn'] = "Saint Kitts & Nevis"; + $c['lc'] = "Saint Lucia"; + $c['pm'] = "Saint Pierre and Miquelon"; + $c['st'] = "Saint Tome (Sao Tome) and Principe"; + $c['vc'] = "Saint Vincent & Grenadines"; + $c['ws'] = "Samoa"; + $c['sm'] = "San Marino"; + $c['sa'] = "Saudi Arabia"; + $c['sn'] = "Senegal"; + $c['rs'] = "Serbia"; + $c['sc'] = "Seychelles"; + $c['sl'] = "Sierra Leone"; + $c['sg'] = "Singapore"; + $c['sk'] = "Slovak Republic"; + $c['si'] = "Slovenia"; + $c['sb'] = "Solomon Islands"; + $c['so'] = "Somalia"; + $c['za'] = "South Africa"; + + $c['es'] = "Spain"; + $c['lk'] = "Sri Lanka"; + $c['sd'] = "Sudan"; + $c['sr'] = "Suriname"; + $c['sj'] = "Svalbard and Jan Mayen Islands"; + $c['sz'] = "Swaziland"; + $c['se'] = "Sweden"; + $c['ch'] = "Switzerland"; + $c['sy'] = "Syria"; + $c['tj'] = "Tadjikistan"; + $c['tw'] = "Taiwan"; + $c['tz'] = "Tanzania"; + $c['th'] = "Thailand"; + $c['ti'] = "Tibet"; + $c['tg'] = "Togo"; + $c['tk'] = "Tokelau"; + $c['to'] = "Tonga"; + $c['tt'] = "Trinidad and Tobago"; + $c['tn'] = "Tunisia"; + $c['tr'] = "Turkey"; + $c['tm'] = "Turkmenistan"; + $c['tc'] = "Turks and Caicos Islands"; + $c['tv'] = "Tuvalu"; + $c['ug'] = "Uganda"; + $c['ua'] = "Ukraine"; + $c['ae'] = "United Arab Emirates"; + $c['gb'] = "United Kingdom"; + $c['us'] = "United States"; + $c['uy'] = "Uruguay"; + $c['um'] = "US Minor Outlying Islands"; + $c['uz'] = "Uzbekistan"; + $c['vu'] = "Vanuatu"; + $c['va'] = "Vatican City State"; + $c['ve'] = "Venezuela"; + $c['vn'] = "Vietnam"; + $c['vg'] = "Virgin Islands (British)"; + $c['vi'] = "Virgin Islands (USA)"; + $c['wf'] = "Wallis and Futuna Islands"; + $c['eh'] = "Western Sahara"; + $c['ye'] = "Yemen"; + + // $c['zr'] = "(deprecated) Zaire"; + $c['zm'] = "Zambia"; + $c['zw'] = "Zimbabwe"; + + + if(!empty($iso) && !empty($c[$iso])) + { + return $c[$iso]; + } + + + return ($iso === null) ? $c : ''; + + } + + + /** + * Get required field markup string + * @return string + */ + public function getRequiredString() + { + return $this->_required_string; + } + + /** + * Set required field markup string + * @param string $string + * @return e_form + */ + public function setRequiredString($string) + { + $this->_required_string = $string; + return $this; + } + + // For Comma separated keyword tags. + function tags($name, $value, $maxlength = 200, $options = array()) + { + if(is_string($options)) parse_str($options, $options); + + $defaults['selectize'] = array( + 'create' => true, + 'maxItems' => vartrue($options['maxItems'], 7), + 'mode' => 'multi', + 'plugins' => array('remove_button'), + ); + + $options = array_replace_recursive($defaults, $options); + + return $this->text($name, $value, $maxlength, $options); + } + + + + + + + /** + * Render Bootstrap Tabs + * @param $array + * @param $options + * @example + * $array = array( + * 'home' => array('caption' => 'Home', 'text' => 'some tab content' ), + * 'other' => array('caption' => 'Other', 'text' => 'second tab content' ) + * ); + */ + function tabs($array,$options = array()) + { + $initTab = varset($options['active'],false); + $id = !empty($options['id']) ? 'id="'.$options['id'].'"' : ''; + $text =' + + '; + + $initTab = varset($options['active'],false); + $tabClass = varset($options['class'],null); + + $text .= ' + +
'; + + $c=0; + foreach($array as $key=>$tab) + { + + + if(is_numeric($key)) + { + $key = 'tab-'.$key; + } + + if($c == 0 & $initTab == false) + { + $initTab = $key; + } + + $active = ($key == $initTab) ? ' active' : ''; + $text .= '
'.$tab['text'].'
'; + $c++; + } + + $text .= ' +
'; + + return $text; + + } + + + /** + * Render Bootstrap Carousel + * @param string $name : A unique name + * @param array $array + * @param array $options : default, interval, pause, wrap + * @return string|array + * @example + * $array = array( + * 'slide1' => array('caption' => 'Slide 1', 'text' => 'first slide content' ), + * 'slide2' => array('caption' => 'Slide 2', 'text' => 'second slide content' ), + * 'slide3' => array('caption' => 'Slide 3', 'text' => 'third slide content' ) + * ); + */ + function carousel($name="e-carousel", $array, $options = null) + { + $interval = null; + $wrap = null; + $pause = null; + $indicators = ''; + $controls = ''; + + $act = varset($options['default'], 0); + + if(isset($options['wrap'])) + { + $wrap = 'data-wrap="'.$options['wrap'].'"'; + } + + if(isset($options['interval'])) + { + $interval = 'data-interval="'.$options['interval'].'"'; + } + + if(isset($options['pause'])) + { + $pause = 'data-pause="'.$options['pause'].'"'; + } + + + $start =' + + + '; + + if(!empty($options['data'])) + { + return array( + 'start' => $start, + 'indicators' => $indicators, + 'inner' => $inner, + 'controls' => $controls, + 'end' => $end + ); + } + + return $start.$indicators.$inner.$controls.$end; // $text; + + } + + /** + * Same as $this->text() except it adds input validation for urls. + * At this stage, checking only for spaces. Should include sef-urls. + */ + function url($name, $value = '', $maxlength = 80, $options= array()) + { + $options['pattern'] = '^\S*$'; + return $this->text($name, $value, $maxlength, $options); + } + + /** + * Text-Field Form Element + * @param $name + * @param $value + * @param $maxlength + * @param $options + * - size: mini, small, medium, large, xlarge, xxlarge + * - class: + * - typeahead: 'users' + * + * @return string + */ + function text($name, $value = '', $maxlength = 80, $options= array()) + { + if(is_string($options)) + { + parse_str($options,$options); + } + + if(!vartrue($options['class'])) + { + $options['class'] = "tbox"; + } + + if(deftrue('BOOTSTRAP')) + { + $options['class'] .= ' form-control'; + } + + /* + if(!vartrue($options['class'])) + { + if($maxlength < 10) + { + $options['class'] = 'tbox input-text span3'; + } + + elseif($maxlength < 50) + { + $options['class'] = 'tbox input-text span7'; + } + + elseif($maxlength > 99) + { + $options['class'] = 'tbox input-text span7'; + } + else + { + $options['class'] = 'tbox input-text'; + } + } + */ + + if(!empty($options['selectize'])) + { + e107::js('core', 'selectize/js/selectize.min.js', 'jquery'); + e107::css('core', 'selectize/css/selectize.css', 'jquery'); + + if(deftrue('BOOTSTRAP') === 3) + { + // e107::css('core', 'selectize/css/selectize.bootstrap3.css', 'jquery'); + } + elseif(deftrue('BOOTSTRAP')) + { + // e107::css('core', 'selectize/css/selectize.bootstrap2.css', 'jquery'); + } + + // Load selectize behavior. + e107::js('core', 'selectize/js/selectize.init.js', 'jquery'); + + $options['selectize']['wrapperClass'] = 'selectize-control'; + $options['selectize']['inputClass'] = 'form-control selectize-input '; + $options['selectize']['dropdownClass'] = 'selectize-dropdown'; + $options['selectize']['dropdownContentClass'] = 'selectize-dropdown-content'; + $options['selectize']['copyClassesToDropdown'] = true; + + $jsSettings = array( + 'id' => vartrue($options['id'], $this->name2id($name)), + 'options' => $options['selectize'], + // Multilingual support. + 'strings' => array( + 'anonymous' => LAN_ANONYMOUS, + ), + ); + + // Merge field settings with other selectize field settings. + e107::js('settings', array('selectize' => array($jsSettings))); + + $options['class'] = ''; + } + + // TODO: remove typeahead. + if(vartrue($options['typeahead'])) + { + if(vartrue($options['typeahead']) == 'users') + { + $options['data-source'] = e_BASE."user.php"; + $options['class'] .= " e-typeahead"; + } + } + + if(vartrue($options['size']) && !is_numeric($options['size'])) + { + $options['class'] .= " input-".$options['size']; + unset($options['size']); // don't include in html 'size='. + } + + $mlength = vartrue($maxlength) ? "maxlength=".$maxlength : ""; + + $type = varset($options['type']) == 'email' ? 'email' : 'text'; // used by $this->email(); + + $options = $this->format_options('text', $name, $options); + + + //never allow id in format name-value for text fields + return "get_attributes($options, $name)." />"; + } + + + /** + * Create a input [type number] + * + * Additional options: + * - decimals: default 0; defines the number of decimals allowed in this field (0 = only integers; 1 = integers & floats with 1 decimal e.g. 4.1, etc.) + * - step: default 1; defines the step for the spinner and the max. number of decimals. If decimals is given, step will be ignored + * - min: default 0; minimum value allowed + * - max: default empty; maximum value allowed + * - pattern: default empty; allows to define an complex input pattern + * + * @param string $name + * @param integer $value + * @param integer $maxlength + * @param array $options decimals, step, min, max, pattern + * @return string + */ + function number($name, $value=0, $maxlength = 200, $options = array()) + { + if(is_string($options)) parse_str($options, $options); + + if(!empty($options['maxlength'])) + { + $maxlength = $options['maxlength']; + } + + unset($options['maxlength']); + + if(empty($options['size'])) + { + $options['size'] = 15; + } + if(empty($options['class'])) + { + $options['class'] = 'tbox number e-spinner input-small '; + } + + if(!empty($options['size'])) + { + $options['class'] .= ' input-'.$options['size']; + unset($options['size']); + } + + $options['class'] .= " form-control"; + $options['type'] ='number'; + + // Not used anymore + //$mlength = vartrue($maxlength) ? "maxlength=".$maxlength : ""; + + // Always define the min. parameter + // defaults to 0 + // setting the min option to a negative value allows negative inputs + $min = " min='".varsettrue($options['min'], '0')."'"; + $max = isset($options['max']) ? " max='".$options['max']."'" : ''; + + if (!empty($options['pattern'])) + { + $pattern = ' pattern="'.trim($options['pattern']).'"'; + } + else + { + $options['pattern'] = '^'; + // ^\-?[0-9]*\.?[0-9]{0,2} + if (varset($options['min'], 0) < 0) + { + $options['pattern'] .= '\-?'; + } + $options['pattern'] .= '[0-9]*'; + + // Integer & Floaat/Double value handling + if (isset($options['decimals'])) + { + if (intval($options['decimals']) > 0) + { + $options['pattern'] .= '\.?[0-9]{0,'.intval($options['decimals']).'}'; + } + + // defined the step based on number of decimals + // 2 = 0.01 > allows integers and float numbers with up to 2 decimals (3.1 = OK; 3.12 = OK; 3.123 = NOK) + // 1 = 0.1 > allows integers and float numbers with up to 2 decimals (3.1 = OK; 3.12 = NOK) + // 0 = 1 > allows only integers, no float values + if (intval($options['decimals']) <= 0) + { + $step = "step='1'"; + } + else + { + $step = "step='0." . str_pad(1, intval($options['decimals']), 0, STR_PAD_LEFT) . "'"; + } + } + else + { + // decimal option not defined + // check for step option (1, 0.1, 0.01, and so on) + // or set default step 1 (integers only) + $step = "step='" . varsettrue($options['step'], '1') . "'"; + } + + $pattern = ' pattern="'.$options['pattern'].'"'; + } + $options = $this->format_options('text', $name, $options); + + //never allow id in format name-value for text fields + if(THEME_LEGACY === false) + { + // return "get_attributes($options, $name)." />"; + return "get_attributes($options, $name)." />"; + } + + return $this->text($name, $value, $maxlength, $options); + } + + + + function email($name, $value, $maxlength = 200, $options = array()) + { + $options['type'] = 'email'; + return $this->text($name,$value,$maxlength,$options); + } + + + + function iconpreview($id, $default, $width='', $height='') // FIXME + { + // XXX - $name ?! + // $parms = $name."|".$width."|".$height."|".$id; + $sc_parameters = 'mode=preview&default='.$default.'&id='.$id; + return e107::getParser()->parseTemplate("{ICONPICKER=".$sc_parameters."}"); + } + + /** + * @param $name + * @param $default value + * @param $label + * @param $options - gylphs=1 + * @param $ajax + */ + function iconpicker($name, $default, $label, $options = array(), $ajax = true) + { + //v2.2.0 + $options['icon'] = 1; + $options['glyph'] = 1; + $options['w'] = 64; + $options['h'] = 64; + $options['media'] = '_icon'; + + if(!isset($options['legacyPath'])) + { + $options['legacyPath'] = "{e_IMAGE}icons"; + } + + return $this->mediapicker($name, $default, $options); + + + /* $options['media'] = '_icon'; + $options['legacyPath'] = "{e_IMAGE}icons"; + + return $this->imagepicker($name, $default, $label, $options);*/ + + + } + + + /** + * Internal Function used by imagepicker, filepicker, mediapicker() + * @param string $category + * @param string $label + * @param string $tagid + * @param null $extras + * @return string + */ + public function mediaUrl($category = '', $label = '', $tagid='', $extras=null) + { + if(is_string($extras)) + { + parse_str($extras,$extras); + } + + $category = str_replace('+', '^', $category); // Bc Fix. + + $cat = ($category) ? '&for='.urlencode($category) : ""; + $mode = vartrue($extras['mode'],'main'); + $action = vartrue($extras['action'],'dialog'); + + + + if(empty($label)) + { + $label = ' Upload an image or file'; + } + + // TODO - option to choose which tabs to display by default. + + $url = e_ADMIN_ABS."image.php?mode={$mode}&action={$action}".$cat; + + if(!empty($tagid)) + { + $url .= '&tagid='.$tagid; + } + + if(!empty($extras['bbcode'])) + { + $url .= '&bbcode='.$extras['bbcode']; + } + + $url .= "&iframe=1"; + + if(vartrue($extras['w'])) + { + $url .= "&w=".$extras['w']; + } + + if(!empty($extras['image'])) + { + $url .= "&image=1"; + } + + if(!empty($extras['glyphs']) || !empty($extras['glyph'])) + { + $url .= "&glyph=1"; + } + + if(!empty($extras['icons']) || !empty($extras['icon'])) + { + $url .= "&icon=1"; + } + + if(!empty($extras['youtube'])) + { + $url .= "&youtube=1"; + } + + if(!empty($extras['video'])) + { + $url .= ($extras['video'] == 2) ? "&video=2" : "&video=1"; + } + + if(!empty($extras['audio'])) + { + $url .= "&audio=1"; + } + + if(!empty($extras['path']) && $extras['path'] == 'plugin') + { + $url .= "&path=".deftrue('e_CURRENT_PLUGIN'); + } + + if(E107_DBG_BASIC) + { + + $title = "Media Manager : ".$category; + } + else + { + $title = LAN_EDIT; + } + + $class = !empty($extras['class']) ? $extras['class']." " : ''; + $title = !empty($extras['title']) ? $extras['title'] : $title; + + $ret = "".$label.""; // using bootstrap. + + if(!e107::getRegistry('core/form/mediaurl')) + { + e107::setRegistry('core/form/mediaurl', true); + } + + return $ret; + } + + + /** + * Avatar Picker + * @param $name - form element name ie. value to be posted. + * @param $curVal - current avatar value. ie. the image-file name or URL. + */ + function avatarpicker($name,$curVal='',$options=array()) + { + + $tp = e107::getParser(); + $pref = e107::getPref(); + + $attr = "aw=".$pref['im_width']."&ah=".$pref['im_height']; + $tp->setThumbSize($pref['im_width'],$pref['im_height']); + + $blankImg = $tp->thumbUrl(e_IMAGE."generic/blank_avatar.jpg",$attr); + $localonly = true; //TODO add a pref for allowing external or internal avatars or both. + $idinput = $this->name2id($name); + $previnput = $idinput."-preview"; + $optioni = $idinput."-options"; + + + $path = (substr($curVal,0,8) == '-upload-') ? '{e_AVATAR}upload/' : '{e_AVATAR}default/'; + $newVal = str_replace('-upload-','',$curVal); + + $img = (strpos($curVal,"://")!==false) ? $curVal : $tp->thumbUrl($path.$newVal); + + if(!$curVal) + { + $img = $blankImg; + } + + $parm = $options; + $classlocal = (!empty($parm['class'])) ? "class='".$parm['class']." e-expandit e-tip avatar'" : " class='img-rounded rounded e-expandit e-tip avatar "; + $class = (!empty($parm['class'])) ? "class='".$parm['class']." e-expandit '" : " class='img-rounded rounded btn btn-default btn-secondary button e-expandit "; + + if($localonly == true) + { + $text = ""; + $text .= "".LAN_EFORM_001.""; + } + else + { + $text = ""; + $text .= ""; + $text .= ""; + } + + $avFiles = e107::getFile()->get_files(e_AVATAR_DEFAULT,".jpg|.png|.gif|.jpeg|.JPG|.GIF|.PNG"); + + $text .= "\n"; + + // Used by usersettings.php right now. + + + + + + + + return $text; + /* + //TODO discuss and FIXME + // Intentionally disable uploadable avatar and photos at this stage + if (false && $pref['avatar_upload'] && FILE_UPLOADS) + { + $text .= "
".LAN_SIGNUP_25." +
".LAN_SIGNUP_34."
"; + } + + if (false && $pref['photo_upload'] && FILE_UPLOADS) + { + $text .= "
".LAN_SIGNUP_26." +
".LAN_SIGNUP_34."
"; + } */ + } + + + + + /** + * Image Picker + + * @param string $name input name + * @param string $default default value + * @param string $label custom label + * @param string $sc_parameters shortcode parameters + * --- SC Parameter list --- + * - media: if present - load from media category table + * - w: preview width in pixels + * - h: preview height in pixels + * - help: tooltip + * - video: when set to true, will enable the Youtube (video) tab. + * @example $frm->imagepicker('banner_image', $_POST['banner_image'], '', 'banner'); // all images from category 'banner_image' + common images. + * @example $frm->imagepicker('banner_image', $_POST['banner_image'], '', 'media=banner&w=600'); + * @return string html output + */ + function imagepicker($name, $default, $previewURL = '', $sc_parameters = '') + { + + $tp = e107::getParser(); + $name_id = $this->name2id($name); + $meta_id = $name_id."-meta"; + + if(is_string($sc_parameters)) + { + if(strpos($sc_parameters, '=') === false) $sc_parameters = 'media='.$sc_parameters; + parse_str($sc_parameters, $sc_parameters); + } + elseif(empty($sc_parameters)) + { + $sc_parameters = array(); + } + + $cat = $tp->toDB(vartrue($sc_parameters['media'])); + + // if(deftrue('e_DEBUG_MEDIAPICKER')) + // { + // v2.2.0 + $sc_parameters['image'] = 1; + $sc_parameters['dropzone'] = 1; + if(!empty($sc_parameters['video'])) // bc fix + { + $sc_parameters['youtube'] = 1; + } + + return $this->mediapicker($name, $default, $sc_parameters); + // } + + + if(empty($sc_parameters['media'])) + { + $sc_parameters['media'] = '_common'; + } + + +// e107::getDebug()->log($sc_parameters); + + $default_thumb = $default; + $class = ''; + + if($default) + { + if($video = $tp->toVideo($default, array('thumb'=>'src'))) + { + $default_url = $video; + $class = 'image-selector-video'; + + } + else + { + if('{' != $default[0]) // legacy path or one without {} + { + list($default_thumb,$default) = $this->imagepickerDefault($default, $sc_parameters); + } + + $default_url = $tp->replaceConstants($default, 'abs'); + } + + + $debugInfo = " +
+			default-thumb: ".$default_thumb."
+			defautlt:   ".$default."
+			default-url: ".$default_url."
+			
"; + + // e107::getDebug()->log($debugInfo); + + + $blank = FALSE; + + + } + else + { + //$default = $default_url = e_IMAGE_ABS."generic/blank.gif"; + $default_url = e_IMAGE_ABS."generic/nomedia.png"; + $blank = TRUE; + $class = 'image-selector-empty'; + } + + + //$width = intval(vartrue($sc_parameters['width'], 150)); + + + if($cat == '_icon') // ICONS + { + $ret = "
"; + $thpath = isset($sc_parameters['nothumb']) || vartrue($hide) ? $default : $default_thumb; + + $label = "
"; + $label .= $tp->toIcon($default_url,array('class'=>'img-responsive img-fluid')); + + //$label = "
"; + //$label .= $tp->toIcon($default_url); + + $label .= "
"; + + // $label = "{$default_url}"; + + + $ret = $this->mediaUrl($cat, $label, $name_id, $sc_parameters); + } + else // Images + { + + $title = (vartrue($sc_parameters['help'])) ? "title='".$sc_parameters['help']."'" : ""; + $width = vartrue($sc_parameters['w'], 120); + $height = vartrue($sc_parameters['h'], 0); + + $ret = "
"; + $att = 'aw='.$width."'&ah=".$height."'"; + $thpath = empty($default) || !empty($video) ? $default_url : $tp->thumbUrl($default_thumb, $att, true); + //isset($sc_parameters['nothumb']) || vartrue($hide) ? + + $label = "{$default_url}"; + + if($cat != 'news' && $cat !='page' && $cat !='' && strpos($cat,'_image')===false) + { + $cat = $cat . "_image"; + } + + $sc_parameters['class'] = 'btn btn-sm btn-default'; + + if($blank === true) + { + $sc_parameters['title'] = LAN_ADD; + $editIcon = $this->mediaUrl($cat, $tp->toGlyph('fa-plus', array('fw'=>1)), $name_id,$sc_parameters); + $previewIcon = ''; + + // @todo drag-n-drop upload code in here. + } + else + { + $editIcon = $this->mediaUrl($cat, $tp->toGlyph('fa-edit', array('fw'=>1)), $name_id,$sc_parameters); + $previewIcon = "".$tp->toGlyph('fa-search', array('fw'=>1)).""; + } + + $ret .= $label; // image + + $ret .= '
+
'.$editIcon.$previewIcon.'
+
'; + } + + + $ret .= "
\n"; + $ret .= ""; + $ret .= ""; + + return $ret; + + } + + +/** + * Media Picker + + * @param string $name input name + * @param string $default default value + * @param string $parms shortcode parameters + * --- $parms list --- + * - media: if present - load from media category table + * - w: preview width in pixels + * - h: preview height in pixels + * - help: tooltip + * - youtube=1 (Enables the Youtube tab) + * - image=1 (Enable the Images tab) + * - video=1 (Enable the Video tab) + * - audio=1 (Enable the Audio tab) + * - glyph=1 (Enable the Glyphs tab). + * @example $frm->imagepicker('banner_image', $_POST['banner_image'], '', 'media=banner&w=600'); + * @return string html output + */ + function mediapicker($name, $default, $parms = '') + { + + + $tp = e107::getParser(); + $name_id = $this->name2id($name); + $meta_id = $name_id."-meta"; + + if(is_string($parms)) + { + if(strpos($parms, '=') === false) $parms = 'media='.$parms; + parse_str($parms, $parms); + } + elseif(empty($parms)) + { + $parms = array(); + } + + + if(empty($parms['media'])) + { + $parms['media'] = '_common'; + } + + $title = !empty($parms['help']) ? "title='".$parms['help']."'" : ""; + + if(!isset($parms['w'])) + { + $parms['w'] = 220; + } + + if(!isset($parms['h'])) + { + $parms['h'] = 190; + } + + + // $width = vartrue($parms['w'], 220); + // $height = vartrue($parms['h'], 190); + // e107::getDebug()->log($parms); + + // Test Files... + // $default = '{e_MEDIA_VIDEO}2018-07/samplevideo_720x480_2mb.mp4'; + // $default = '{e_MEDIA_FILE}2016-03/Colony_Harry_Gregson_Williams.mp3'; + // $default = '{e_PLUGIN}gallery/images/butterfly.jpg'; + // $default = 'NuIAYHVeFYs.youtube'; + // $default = ''; // empty + // $default = '{e_MEDIA_IMAGE}2018-07/Jellyfish.jpg'; + + $class = ''; + + if($parms['icon']) + { + $class = 'icon-preview mediaselector-container-icon'; + $parms['type'] = 'icon'; + } + + $preview = e107::getMedia()->previewTag($default,$parms); + + $cat = $tp->toDB(vartrue($parms['media'])); + + $ret = "
"; + + $parms['class'] = 'btn btn-sm btn-default'; + + $dropzone = !empty($parms['dropzone']) ? " dropzone" : ""; + // $parms['modal-delete-label'] = LAN_DELETE; + + if(empty($preview)) + { + $parms['title'] = LAN_ADD; + $editIcon = $this->mediaUrl($cat, $tp->toGlyph('fa-plus', array('fw'=>1)), $name_id,$parms); + $previewIcon = ''; + } + else + { + $editIcon = $this->mediaUrl($cat, $tp->toGlyph('fa-edit', array('fw'=>1)), $name_id,$parms); + // $previewIcon = "".$tp->toGlyph('fa-search', array('fw'=>1)).""; + $previewIcon = ''; + } + + + if(!empty($parms['icon'])) // empty overlay without button. + { + $parms['class'] = ''; + $editIcon = $this->mediaUrl($cat, "", $name_id,$parms); + } + + $ret .= "
"; + + $ret .= $preview; // image, video. audio tag etc. + + $ret .= '
+
'.$editIcon.$previewIcon.'
+
'; + + $ret .= "
\n"; + $ret .= ""; + $ret .= ""; + + if(empty($dropzone)) + { + return $ret; + } + // Drag-n-Drop Upload + // @see https://www.dropzonejs.com/#server-side-implementation + + e107::js('footer', e_WEB_ABS."lib/dropzone/dropzone.min.js"); + e107::css('url', e_WEB_ABS."lib/dropzone/dropzone.min.css"); + e107::css('inline', " + .dropzone { background: transparent; border:0 } + "); + + $INLINEJS = " + Dropzone.autoDiscover = false; + $(function() { + $('#".$name_id."_prev').dropzone({ + url: '".e_JS."plupload/upload.php?for=".$cat."', + createImageThumbnails: false, + uploadMultiple :false, + dictDefaultMessage: \"".defset('LAN_UI_DROPZONE_DROP_FILES', "Drop files here to upload")."\", + maxFilesize: ".(int) ini_get('upload_max_filesize').", + success: function (file, response) { + + file.previewElement.classList.add('dz-success'); + + // console.log(response); + + if(response) + { + var decoded = jQuery.parseJSON(response); + console.log(decoded); + if(decoded.preview && decoded.result) + { + $('#".$name_id."').val(decoded.result); + $('#".$name_id."_prev').html(decoded.preview); + } + else if(decoded.error) + { + file.previewElement.classList.add('dz-error'); + $('#".$name_id."_prev').html(decoded.error.message); + } + } + + }, + error: function (file, response) { + file.previewElement.classList.add('dz-error'); + } + }); + }); + + "; + + + e107::js('footer-inline', $INLINEJS); + + return $ret; + + } + + + + + + + + private function imagepickerDefault($path, $parms=array()) + { + $tp = e107::getParser(); + + if(!empty($parms['legacyPath'])) // look in a specific path. + { + $legacyDefault = rtrim($parms['legacyPath'],'/')."/".$path; + $legacyRel = $tp->replaceConstants($legacyDefault); + + if(is_readable($legacyRel)) + { + return array($legacyDefault, $legacyDefault); + } + else + { + // e107::getDebug()->log("Legacy Default:".$legacyDefault); + // e107::getDebug()->log("wasnt found:".$legacyRel); + } + + } + + $path = str_replace('e_MEDIA_IMAGE/','{e_MEDIA_IMAGE}',$path); + + $default_thumb = $tp->createConstants($path, 'nice'); + $default = $tp->createConstants($path, 'mix'); + + return array($default_thumb, $default); + + } + + + /** + * File Picker + * @param string name eg. 'myfield' or 'myfield[]' + * @param mixed default + * @param string label + * @param mixed sc_parameters + */ + function filepicker($name, $default, $label = '', $sc_parameters = '') + { + $tp = e107::getParser(); + $name_id = $this->name2id($name); + + if(is_string($sc_parameters)) + { + if(strpos($sc_parameters, '=') === false) $sc_parameters = 'media='.$sc_parameters; + parse_str($sc_parameters, $sc_parameters); + } + + $cat = vartrue($sc_parameters['media']) ? $tp->toDB($sc_parameters['media']) : "_common_file"; + + $ret = ''; + + if($sc_parameters['data'] === 'array') + { + // Do not use $this->hidden() method - as it will break 'id' value. + $ret .= ""; + $ret .= ""; + $ret .= ""; + + $default = $default['path']; + } + else + { + $ret .= ""; + } + + + $default_label = ($default) ? $default : LAN_CHOOSE_FILE; + $label = "".basename($default_label).""; + + $sc_parameters['mode'] = 'main'; + $sc_parameters['action'] = 'dialog'; + + + // $ret .= $this->mediaUrl($cat, $label,$name_id,"mode=dialog&action=list"); + $ret .= $this->mediaUrl($cat, $label,$name_id,$sc_parameters); + + + + + return $ret; + + + } + + + + + /** + * Date field with popup calendar // NEW in 0.8/2.0 + * on Submit returns unix timestamp or string value. + * @param string $name the name of the field + * @param integer $datestamp UNIX timestamp - default value of the field + * @param array or str + * @param string $options['type'] date or datetime + * @param string $options['format'] strftime format eg. '%Y-%m-%d' + * @param string $options['timezone'] eg. 'America/Los_Angeles' - intended timezone of the date/time entered. (offsets UTC value) + * @example $frm->datepicker('my_field',time(),'type=date'); + * @example $frm->datepicker('my_field',time(),'type=datetime&inline=1'); + * @example $frm->datepicker('my_field',time(),'type=date&format=yyyy-mm-dd'); + * @example $frm->datepicker('my_field',time(),'type=datetime&format=MM, dd, yyyy hh:ii'); + * @example $frm->datepicker('my_field',time(),'type=datetime&return=string'); + * + * @url http://trentrichardson.com/examples/timepicker/ + * @return string + */ + function datepicker($name, $datestamp = false, $options = null) + { + if(vartrue($options) && is_string($options)) + { + parse_str($options,$options); + } + + $type = varset($options['type']) ? trim($options['type']) : "date"; // OR 'datetime' + $dateFormat = varset($options['format']) ? trim($options['format']) :e107::getPref('inputdate', '%Y-%m-%d'); + $ampm = (preg_match("/%l|%I|%p|%P/",$dateFormat)) ? 'true' : 'false'; + $value = null; + $hiddenValue = null; + $useUnix = (isset($options['return']) && ($options['return'] === 'string')) ? 'false' : 'true'; + $id = $this->name2id($name); + $classes = array('date' => 'e-date', 'datetime' => 'e-datetime'); + + if($type == 'datetime' && !varset($options['format'])) + { + $dateFormat .= " ".e107::getPref('inputtime', '%H:%M:%S'); + } + + $dformat = e107::getDate()->toMask($dateFormat); + + // If default value is set. + if ($datestamp && $datestamp !='0000-00-00') // date-field support. + { + if(!is_numeric($datestamp)) + { + $datestamp = strtotime($datestamp); + } + + // Convert date to proper (selected) format. + $hiddenValue = $value = e107::getDate()->convert_date($datestamp, $dformat); + + if ($useUnix === 'true') + { + $hiddenValue = $datestamp; + } + } + + $class = (isset($classes[$type])) ? $classes[$type] : "tbox e-date"; + $size = vartrue($options['size']) ? intval($options['size']) : 40; + $required = vartrue($options['required']) ? "required" : ""; + $firstDay = vartrue($options['firstDay']) ? $options['firstDay'] : 0; + $xsize = (vartrue($options['size']) && !is_numeric($options['size'])) ? $options['size'] : 'xlarge'; + $disabled = vartrue($options['disabled']) ? "disabled" : ""; + $timezone = ''; + + if(!empty($options['timezone'])) // since datetimepicker does not support timezones and assumes the browser timezone is the intended timezone. + { + date_default_timezone_set($options['timezone']); + $targetOffset = date('Z'); + date_default_timezone_set(USERTIMEZONE); + $timezone = "data-date-timezone-offset='".$targetOffset."'"; + } + + $text = ""; + + if(vartrue($options['inline'])) + { + $text .= "
"; + $text .= ""; + } + else + { + $text .= ""; + $ftype = (!empty($options['debug'])) ? 'text' : 'hidden'; + $text .= ""; + } + + // TODO use Library Manager... + e107::css('core', 'bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css', 'jquery'); + e107::js('footer', '{e_WEB}js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js', 'jquery', 4); + e107::js('footer', '{e_WEB}js/bootstrap-datetimepicker/js/bootstrap-datetimepicker.init.js', 'jquery', 5); + + if(e_LANGUAGE !== 'English') + { + e107::js('footer-inline', e107::getDate()->buildDateLocale()); + } + + return $text; + } + + + /** + * Render a simple user dropdown list. + * @param string $name - form field name + * @param null $val - current value + * @param array $options + * @param string $options['group'] if == 'class' then users will be sorted into userclass groups. + * @param string $options['fields'] + * @param string $options['classes'] - single or comma-separated list of user-classes members to include. + * @param string $options['excludeSelf'] = exlude logged in user from list. + * @param string $options['return'] if == 'array' an array is returned. + * @param string $options['return'] if == 'sqlWhere' an sql query is returned. + * @return string select form element. + */ + public function userlist($name, $val=null, $options=array()) + { + + $fields = (!empty($options['fields'])) ? $options['fields'] : "user_id,user_name,user_class"; + $class = (!empty($options['classes'])) ? $options['classes'] : e_UC_MEMBER ; // all users sharing the same class as the logged-in user. + + $class = str_replace(" ","",$class); + + switch ($class) + { + case e_UC_ADMIN: + $where = "user_admin = 1"; + $classList = e_UC_ADMIN; + break; + + case e_UC_MEMBER: + $where = "user_ban = 0"; + $classList = e_UC_MEMBER; + break; + + case e_UC_NOBODY: + return ""; + break; + + case 'matchclass': + $where = "user_class REGEXP '(^|,)(".str_replace(",","|", USERCLASS).")(,|$)'"; + $classList = USERCLASS; + $clist = explode(",",USERCLASS); + if(count($clist) > 1 && !isset($options['group'])) // group classes by default if more than one found. + { + $options['group'] = 'class'; + } + break; + + default: + $where = "user_class REGEXP '(^|,)(".str_replace(",","|", $class).")(,|$)'"; + $classList = $class; + break; + } + + + if(!empty($options['return']) && $options['return'] == 'sqlWhere') // can be used by user.php ajax method.. + { + return $where; + } + + $users = e107::getDb()->retrieve("user",$fields, "WHERE ".$where." ORDER BY user_name LIMIT 1000",true); + + if(empty($users)) + { + return LAN_UNAVAILABLE; + } + + $opt = array(); + + if(!empty($options['group']) && $options['group'] == 'class') + { + $classes = explode(',',$classList); + + foreach($classes as $cls) + { + $cname = e107::getUserClass()->getName($cls); + + $cname = str_replace('_',' ', trim($cname)); + foreach($users as $u) + { + $uclass = explode(',',$u['user_class']); + + if(($classList == e_UC_ADMIN) || ($classList == e_UC_MEMBER) || in_array($cls,$uclass)) + { + $id = $u['user_id']; + + if(!empty($options['excludeSelf']) && ($id == USERID)) + { + continue; + } + + $opt[$cname][$id] = $u['user_name']; + } + } + + + } + + } + else + { + foreach($users as $u) + { + $id = $u['user_id']; + $opt[$id] = $u['user_name']; + } + + } + + + ksort($opt); + + + if(!empty($options['return']) && $options['return'] == 'array') // can be used by user.php ajax method.. + { + return $opt; + } + + return $this->select($name,$opt,$val,$options, varset($options['default'],null)); + + } + + + + /** + * User auto-complete search + * XXX EXPERIMENTAL - subject to change. + * @param string $name_fld field name for user name + * @param string $id_fld field name for user id + * @param string $default_name default user name value + * @param integer $default_id default user id + * @param array|string $options [optional] 'readonly' (make field read only), 'name' (db field name, default user_name) + * @return string HTML text for display + */ + /* + function userpicker($name_fld, $id_fld='', $default_name, $default_id, $options = array()) + { + if(!is_array($options)) + { + parse_str($options, $options); + } + + $default_name = vartrue($default_name, ''); + $default_id = vartrue($default_id, ''); + + $default_options = array(); + if (!empty($default_name)) + { + $default_options = array( + array( + 'value' => $default_id, + 'label' => $default_name, + ), + ); + } + + $defaults['selectize'] = array( + 'loadPath' => e_BASE . 'user.php', + 'create' => false, + 'maxItems' => 1, + 'mode' => 'multi', + 'options' => $default_options, + ); + + //TODO FIXME Filter by userclass. - see $frm->userlist(). + + $options = array_replace_recursive($defaults, $options); + + $ret = $this->text($name_fld, $default_id, 20, $options); + + return $ret; + } + */ + + + /** + * User Field - auto-complete search + * @param string $name form element name + * @param string|array $value comma separated list of user ids or array of userid=>username pairs. + * @param array|string $options [optional] + * @param int $options['limit'] Maximum number of users + * @param string $options['id'] Custom id + * @param string $options['inline'] Inline ID. + * + * @example $frm->userpicker('author', 1); + * @example $frm->userpicker('authors', "1,2,3"); + * @example $frm->userpicker('author', array('user_id'=>1, 'user_name'=>'Admin'); + * @example $frm->userpicker('authors', array(0=>array('user_id'=>1, 'user_name'=>'Admin', 1=>array('user_id'=>2, 'user_name'=>'John')); + * + * @todo $options['type'] = 'select' - dropdown selections box with data returned as array instead of comma-separated. + * @return string HTML text for display + */ + function userpicker($name, $value, $options = array()) + { + if(!is_array($options)) + { + parse_str($options, $options); + } + + $defaultItems = array(); + + if(is_array($value)) + { + if(isset($value[0]))// multiple users. + { + foreach($value as $val) + { + $defaultItems[] = array('value'=>$val['user_id'], 'label'=>$val['user_name']); + } + + } + else // single user + { + $defaultItems[] = array('value'=>$value['user_id'], 'label'=>$value['user_name']); + } + + } + elseif(!empty($value)) /// comma separated with user-id lookup. + { + $tmp = explode(",", $value); + foreach($tmp as $uid) + { + if($user = e107::user($uid)) + { + $defaultItems[] = array('value'=>$user['user_id'], 'label'=>$user['user_name']); + } + } + } + + $parms = array( + 'selectize' => array( + 'loadPath' => e_HTTP.'user.php', + 'create' => false, + 'maxItems' => 1, + 'mode' => 'multi', + 'options' => $defaultItems + ) + ); + + if(!empty($options['limit'])) + { + $parms['selectize']['maxItems'] = intval($options['limit']); + } + + if(!empty($options['id'])) + { + $parms['id'] = $options['id']; + } + + if(!empty($options['inline'])) + { + $parms['selectize']['e_editable'] = $options['inline']; + } + + //TODO FIXME Filter by userclass. - see $frm->userlist(). + + $defValues = array(); + + foreach($defaultItems as $val) + { + $defValues[] = $val['value']; + } + + $parms = array_merge($parms, $options); + + $ret = $this->text($name, implode(",",$defValues), 100, $parms); + + return $ret; + } + + + + + + + /** + * A Rating element + * @var $text + */ + function rate($table,$id,$options=null) + { + $table = preg_replace('/\W/', '', $table); + $id = intval($id); + + return e107::getRate()->render($table, $id, $options); + } + + function like($table,$id,$options=null) + { + $table = preg_replace('/\W/', '', $table); + $id = intval($id); + + return e107::getRate()->renderLike($table,$id,$options); + } + + + /** + * File Upload form element. + * @param $name + * @param array $options (optional) array('multiple'=>1) + * @return string + */ + function file($name, $options = array()) + { + if(e_ADMIN_AREA && empty($options['class'])) + { + $options = array('class'=>'tbox well file'); + } + + $options = $this->format_options('file', $name, $options); + + + + //never allow id in format name-value for text fields + return "get_attributes($options, $name)." />"; + } + + function upload($name, $options = array()) + { + return 'Ready to use upload form fields, optional - file list view'; + } + + function password($name, $value = '', $maxlength = 50, $options = array()) + { + if(is_string($options)) parse_str($options, $options); + + $addon = ""; + $gen = ""; + + if(vartrue($options['generate'])) + { + $gen = ' '.LAN_GENERATE.' '; + + if(empty($options['nomask'])) + { + $gen .= ''.LAN_SHOW.'
'; + } + } + + if(vartrue($options['strength'])) + { + $addon .= "
"; + } + + $options['pattern'] = vartrue($options['pattern'],'[\S].{2,}[\S]'); + $options['required'] = varset($options['required'], 1); + $options['class'] = vartrue($options['class'],'e-password tbox'); + + + e107::js('core', 'password/jquery.pwdMeter.js', 'jquery', 2); + + e107::js('footer-inline', ' + $(".e-password").pwdMeter({ + minLength: 6, + displayGeneratePassword: true, + generatePassText: "Generate", + randomPassLength: 12 + }); + '); + + if(deftrue('BOOTSTRAP')) + { + $options['class'] .= ' form-control'; + } + + if(vartrue($options['size']) && !is_numeric($options['size'])) + { + $options['class'] .= " input-".$options['size']; + unset($options['size']); // don't include in html 'size='. + } + + $type = empty($options['nomask']) ? 'password' : 'text'; + + $options = $this->format_options('text', $name, $options); + + + //never allow id in format name-value for text fields + $text = "get_attributes($options, $name)." />"; + + if(empty($gen) && empty($addon)) + { + return $text; + } + else + { + return "".$text.$gen."".vartrue($addon); + } + + } + + + /** + * Render Pagination using 'nextprev' shortcode. + * @param string $url eg. e_REQUEST_SELF.'?from=[FROM]' + * @param int $total total records + * @param int $from value to replace [FROM] with in the URL + * @param int $perPage number of items per page + * @param array $options template, type, glyphs + * @return string + */ + public function pagination($url='', $total=0, $from=0, $perPage=10, $options=array()) + { + + if(empty($total) || empty($perPage)) + { + return ''; + } + + if(!is_numeric($total)) + { + return ''; + } + + + + require_once(e_CORE."shortcodes/single/nextprev.php"); + + $nextprev = array( + 'tmpl_prefix' => varset($options['template'],'default'), + 'total' => intval($total), + 'amount' => intval($perPage), + 'current' => intval($from), + 'url' => urldecode($url), + 'type' => varset($options['type'],'record'), // page|record + 'glyphs' => vartrue($options['glyphs'],false) // 1|0 + ); + + // e107::getDebug()->log($nextprev); + + return nextprev_shortcode($nextprev); + } + + + + /** + * Render a bootStrap ProgressBar. + * @param string $name + * @param number|string $value + * @param array $options + * @example Use + */ + public function progressBar($name,$value,$options=array()) + { + if(!deftrue('BOOTSTRAP')) // Legacy ProgressBar. + { + $barl = (file_exists(THEME.'images/barl.png') ? THEME_ABS.'images/barl.png' : e_PLUGIN_ABS.'poll/images/barl.png'); + $barr = (file_exists(THEME.'images/barr.png') ? THEME_ABS.'images/barr.png' : e_PLUGIN_ABS.'poll/images/barr.png'); + $bar = (file_exists(THEME.'images/bar.png') ? THEME_ABS.'images/bar.png' : e_PLUGIN_ABS.'poll/images/bar.png'); + + return "
+
+
"; + } + + $class = vartrue($options['class'],''); + $target = $this->name2id($name); + + $striped = (vartrue($options['btn-label'])) ? ' progress-striped active' : ''; + + if(strpos($value,'/')!==false) + { + $label = $value; + list($score,$denom) = explode('/',$value); + + $multiplier = 100 / (int) $denom; + + $value = (int) $score * (int) $multiplier; + $percVal = number_format($value,0).'%'; + } + else + { + $percVal = number_format($value,0).'%'; + $label = $percVal; + } + + if(!empty($options['label'])) + { + $label = $options['label']; + } + + + $text = "
+
"; + $text .= $label; + $text .= "
+
"; + + $loading = vartrue($options['loading'], defset('LAN_LOADING', "Loading")); + + $buttonId = $target.'-start'; + + + + if(vartrue($options['btn-label'])) + { + $interval = vartrue($options['interval'],1000); + $text .= ''.$options['btn-label'].''; + $text .= ' '.LAN_CANCEL.''; + } + + + return $text; + + } + + + /** + * Textarea Element + * @param $name + * @param $value + * @param $rows + * @param $cols + * @param $options + * @param $count + * @return string + */ + function textarea($name, $value, $rows = 10, $cols = 80, $options = array(), $counter = false) + { + if(is_string($options)) parse_str($options, $options); + // auto-height support + + if(empty($options['class'])) + { + $options['class'] = ''; + } + + if(vartrue($options['size']) && !is_numeric($options['size'])) + { + $options['class'] .= " form-control input-".$options['size']; + unset($options['size']); // don't include in html 'size='. + } + elseif(!vartrue($options['noresize'])) + { + $options['class'] = (isset($options['class']) && $options['class']) ? $options['class'].' e-autoheight' : 'tbox col-md-7 span7 e-autoheight form-control'; + } + + $options = $this->format_options('textarea', $name, $options); + +// print_a($options); + //never allow id in format name-value for text fields + return "".(false !== $counter ? $this->hidden('__'.$name.'autoheight_opt', $counter) : ''); + } + + /** + * Bbcode Area. Name, value, template, media-Cat, size, options array eg. counter + * IMPORTANT: $$mediaCat is also used is the media-manager category identifier + * @param string $name + * @param mixed $value + * @param string $template + * @param string $mediaCat _common + * @param string $size : small | medium | large + * @param array $options array(); + * @param bool $options['wysiwyg'] when set to false will disable wysiwyg if active. + * @param string $options['class'] override class. + * @param string $options['id'] + */ + function bbarea($name, $value, $template = '', $mediaCat='_common', $size = 'large', $options = array()) + { + if(is_string($options)) parse_str($options, $options); + //size - large|medium|small + //width should be explicit set by current admin theme + // $size = 'input-large'; + $height = ''; + $cols = 70; + + switch($size) + { + case 'tiny': + $rows = '3'; + $cols = 50; + // $height = "style='height:250px'"; // inline required for wysiwyg + break; + + + case 'small': + $rows = '7'; + $height = "style='height:230px'"; // inline required for wysiwyg + $size = "input-block-level"; + break; + + case 'medium': + $rows = '10'; + + $height = "style='height:375px'"; // inline required for wysiwyg + $size = "input-block-level"; + break; + + case 'large': + default: + $rows = '20'; + $size = 'large input-block-level'; + // $height = "style='height:500px;width:1025px'"; // inline required for wysiwyg + break; + } + + // auto-height support +/* + $bbbar = ''; + $wysiwyg = null; + $wysiwygClass = ' e-wysiwyg'; + + if(isset($options['wysiwyg'])) + { + $wysiwyg = $options['wysiwyg']; + } + + if($wysiwyg === false) + { + $wysiwygClass = ''; + } + + $options['class'] = 'tbox bbarea '.($size ? ' '.$size : '').$wysiwygClass.' e-autoheight form-control'; +*/ + $options['class'] = 'tbox bbarea '.($size ? ' '.$size : '').' e-wysiwyg e-autoheight form-control'; + + if (isset($options['id']) && !empty($options['id'])) + { + $help_tagid = $this->name2id($options['id'])."--preview"; + } + else + { + $help_tagid = $this->name2id($name)."--preview"; + } + + if (!isset($options['wysiwyg'])) + { + $options['wysiwyg'] = true; + } + + //if(e107::wysiwyg(true) === false || $wysiwyg === false) // bbarea loaded, so activate wysiwyg (if enabled in preferences) + if(e107::wysiwyg($options['wysiwyg'],true) === 'bbcode') // bbarea loaded, so activate wysiwyg (if enabled in preferences) + { + $options['other'] = "onselect='storeCaret(this);' onclick='storeCaret(this);' onkeyup='storeCaret(this);' {$height}"; + } + else + { + $options['other'] = " ".$height; + } + + + $counter = vartrue($options['counter'],false); + + $ret = "
+
\n"; + + + if(e107::wysiwyg() === true) // && $wysiwyg !== false) + { + $eParseList = e107::getConfig()->get('e_parse_list'); + + if(!empty($eParseList)) + { + $opts = array( + 'field' => $name, + ); + + foreach($eParseList as $plugin) + { + $hookObj = e107::getAddon($plugin, 'e_parse'); + + if($tmp = e107::callMethod($hookObj, 'toWYSIWYG', $value, $opts)) + { + $value = $tmp; + } + } + } + } + + + $ret .= e107::getBB()->renderButtons($template,$help_tagid); + $ret .= $this->textarea($name, $value, $rows, $cols, $options, $counter); // higher thank 70 will break some layouts. + + $ret .= "
\n"; + + $_SESSION['media_category'] = $mediaCat; // used by TinyMce. + + + + + return $ret; + + // Quick fix - hide TinyMCE links if not installed, dups are handled by JS handler + /* + + e107::getJs()->footerInline(" + if(typeof tinyMCE === 'undefined') + { + \$$('a.e-wysiwyg-switch').invoke('hide'); + } + "); + */ + + + } + + /** + * Render a checkbox + * @param string $name + * @param mixed $value + * @param boolean $checked + * @param mixed $options query-string or array or string for a label. eg. label=Hello&foo=bar or array('label'=>Hello') or 'Hello' + * @return string + */ + function checkbox($name, $value, $checked = false, $options = array()) + { + if(!is_array($options)) + { + if(strpos($options,"=")!==false) + { + parse_str($options, $options); + } + elseif(is_array($options)) + { + // do nothing. + } + else // Assume it's a label. + { + $options = array('label'=>$options); + } + + } + + $labelClass = (!empty($options['inline'])) ? 'checkbox-inline' : 'checkbox'; + $labelTitle = ''; + + $options = $this->format_options('checkbox', $name, $options); + + $options['checked'] = $checked; //comes as separate argument just for convenience + + $text = ""; + + $active = ($checked === true) ? " active" : ""; // allow for styling if needed. + + if(!empty($options['label'])) // add attributes to "; + } + + function help($text) + { + return !empty($text) ? '
'.$text.'
' : ''; + } + + function select_open($name, $options = array()) + { + + if(!is_array($options)) parse_str($options, $options); + + + if(!empty($options['size']) && !is_numeric($options['size'])) + { + if(!empty($options['class'])) + { + $options['class'] .= " form-control input-".$options['size']; + } + else + { + $options['class'] = "form-control input-".$options['size']; + } + + unset($options['size']); // don't include in html 'size='. + } + + + $options = $this->format_options('select', $name, $options); + + return " + + + + + + + + +
+
+ + + + + + + */ + } + + + /** + * @param $name + * @param null $current_value + * @param null $uc_options + * @param array $select_options multiple, default + * @param array $opt_options + * @return string + */ + function uc_select($name, $current_value=null, $uc_options=null, $select_options = array(), $opt_options = array()) + { + +/* var_dump($name); + var_dump($current_value); +var_dump($uc_options); +var_dump($select_options);*/ + + + if(!empty($select_options['multiple']) && substr($name,-1) != ']') + { + $name .= '[]'; + } + + if(($current_value === null || $current_value === '') && !empty($uc_options)) // make the first in the opt list the default value. + { + $tmp = explode(",", $uc_options); + $current_value = e107::getUserClass()->getClassFromKey($tmp[0]); + + if(isset($select_options['default'])) + { + $current_value = (int) $select_options['default']; + } + } + + if(!empty($current_value) && !is_numeric($current_value)) // convert name to id. + { + //$current_value = $this->_uc->getID($current_value); + // issue #3249 Accept also comma separated values + if (!is_array($current_value)) + { + $current_value = explode(',', $current_value); + } + $tmp = array(); + foreach($current_value as $val) + { + if (!empty($val)) + { + $tmp[] = !is_numeric($val) ? $this->_uc->getID(trim($val)) : (int) $val; + } + } + $current_value = implode(',', $tmp); + unset($tmp); + } + + $text = $this->select_open($name, $select_options)."\n"; + $text .= $this->_uc->vetted_tree($name, array($this, '_uc_select_cb'), $current_value, $uc_options, $opt_options)."\n"; + $text .= $this->select_close(); + + return $text; + } + + // Callback for vetted_tree - Creates the option list for a selection box + function _uc_select_cb($treename, $classnum, $current_value, $nest_level) + { + $classIndex = abs($classnum); // Handle negative class values + $classSign = (substr($classnum, 0, 1) == '-') ? '-' : ''; + + if($classnum == e_UC_BLANK) + return $this->option(' ', ''); + + $tmp = explode(',', $current_value); + if($nest_level == 0) + { + $prefix = ''; + $style = "font-weight:bold; font-style: italic;"; + } + elseif($nest_level == 1) + { + $prefix = '  '; + $style = "font-weight:bold"; + } + else + { + $prefix = '  '.str_repeat('--', $nest_level - 1).'>'; + $style = ''; + } + return $this->option($prefix.$this->_uc->uc_get_classname($classnum), $classSign.$classIndex, ($current_value !== '' && in_array($classnum, $tmp)), array("style"=>"{$style}"))."\n"; + } + + + function optgroup_open($label, $disabled = false, $options = null) + { + return "\n"; + } + + /** + * "; + } + + + /** + * Use selectbox() instead. + */ + function option_multi($option_array, $selected = false, $options = array()) + { + if(is_string($option_array)) + { + parse_str($option_array, $option_array); + } + + $text = ''; + + if(empty($option_array)) + { + return $this->option('',''); + } + + $opts = $options; + + foreach ((array) $option_array as $value => $label) + { + if(is_array($label)) + { + $text .= $this->optgroup($value, $label, $selected, $options, 0); + } + else + { + $sel = is_array($selected) ? in_array($value, $selected) : ($value == $selected); + + if(!empty($options['optDisabled']) && is_array($options['optDisabled'])) + { + $opts['disabled'] = in_array($value, $options['optDisabled']); + } + + $text .= $this->option($label, $value, $sel, $opts)."\n"; + } + } + + return $text; + } + + + /** + * No compliant, but it works. + * @param $value + * @param $label + * @param $selected + * @param $options + * @param int $level + * @return string + */ + private function optgroup($value, $label, $selected, $options, $level=1) + { + $level++; + $text = $this->optgroup_open($value, null, array('class'=>'level-'.$level)); + + $opts = $options; + + foreach($label as $val => $lab) + { + if(is_array($lab)) + { + $text .= $this->optgroup($val,$lab,$selected,$options,$level); + } + else + { + if(!empty($options['optDisabled']) && is_array($options['optDisabled'])) + { + $opts['disabled'] = in_array($val, $options['optDisabled']); + } + + $text .= $this->option($lab, $val, (is_array($selected) ? in_array($val, $selected) : $selected == $val), $opts)."\n"; + } + + } + + $text .= $this->optgroup_close(); + + return $text; + } + + + + + + function optgroup_close() + { + return "\n"; + } + + function select_close() + { + return ""; + } + + function hidden($name, $value, $options = array()) + { + $options = $this->format_options('hidden', $name, $options); + + return "get_attributes($options, $name, $value)." />"; + } + + /** + * Generate hidden security field + * @return string + */ + function token() + { + return ""; + } + + function submit($name, $value, $options = array()) + { + $options = $this->format_options('submit', $name, $options); + return "get_attributes($options, $name, $value)." />"; + } + + function submit_image($name, $value, $image, $title='', $options = array()) + { + $tp = e107::getParser(); + + if(!empty($options['icon'])) + { + $customIcon = $options['icon']; + unset($options['icon']); + } + + $options = $this->format_options('submit_image', $name, $options); + switch ($image) + { + case 'edit': + $icon = (e_ADMIN_AREA === true) ? ADMIN_EDIT_ICON : $tp->toIcon("e-edit-32"); + $options['class'] = $options['class'] == 'action' ? 'btn btn-default btn-secondary action edit' : $options['class']; + break; + + case 'delete': + $icon = (e_ADMIN_AREA === true) ? ADMIN_DELETE_ICON : $tp->toIcon('fa-trash.glyph'); + $options['class'] = $options['class'] == 'action' ? 'btn btn-default btn-secondary action delete' : $options['class']; + $options['other'] = 'data-confirm="'.LAN_JSCONFIRM.'"'; + break; + + case 'execute': + $icon = (e_ADMIN_AREA === true) ? ADMIN_EXECUTE_ICON : $tp->toIcon('fa-power-off.glyph'); + $options['class'] = $options['class'] == 'action' ? 'btn btn-default btn-secondary action execute' : $options['class']; + break; + + case 'view': + $icon = $tp->toIcon("e-view-32"); + $options['class'] = $options['class'] == 'action' ? 'btn btn-default btn-secondary action view' : $options['class']; + break; + } + + $options['title'] = $title;//shorthand + + if(!empty($customIcon)) + { + $icon = $customIcon; + } + + return ""; + + + } + + /** + * Alias of admin_button, adds the etrigger_ prefix required for UI triggers + * @see e_form::admin_button() + */ + function admin_trigger($name, $value, $action = 'submit', $label = '', $options = array()) + { + return $this->admin_button('etrigger_'.$name, $value, $action, $label, $options); + } + + + /** + * Generic Button Element. + * @param string $name + * @param string $value + * @param string $action [optional] default is submit - use 'dropdown' for a bootstrap dropdown button. + * @param string $label [optional] + * @param string|array $options [optional] + * @return string + */ + public function button($name, $value, $action = 'submit', $label = '', $options = array()) + { + if(deftrue('BOOTSTRAP') && $action == 'dropdown' && is_array($value)) + { + // $options = $this->format_options('admin_button', $name, $options); + $options['class'] = vartrue($options['class']); + + $align = vartrue($options['align'],'left'); + + $text = '
+ + '.($label ? $label : LAN_NO_LABEL_PROVIDED).' + + + +
'; + + return $text; + } + + + + return $this->admin_button($name, $value, $action, $label, $options); + + } + + /** + * Render a Breadcrumb in Bootstrap format. + * @param $array + * @param $array[url] + * @param $array[text] + */ + function breadcrumb($array) + { + if(!is_array($array)){ return; } + + $opt = array(); + + $homeicon = (deftrue('FONTAWESOME')) ? 'fa-home' : 'icon-home.glyph'; + $homeIcon = e107::getParser()->toGlyph($homeicon,false); + + + $opt[] = "".$homeIcon.""; // Add Site-Pref to disable? + + $text = '"; + + // return print_a($opt,true); + + return $text; + + } + + + /** + * Render a direct link admin-edit button on the frontend. + * @param $url + * @param string $perms + * @return string + */ + public function instantEditButton($url, $perms='0') + { + if(deftrue("BOOTSTRAP") && getperms($perms)) + { + return "".e107::getParser()->toGlyph('fa-edit').""; + } + + return ''; + + } + + + + + /** + * Admin Button - for front-end, use button(); + * @param string $name + * @param string $value + * @param string $action [optional] default is submit + * @param string $label [optional] + * @param string|array $options [optional] + * @return string + */ + function admin_button($name, $value, $action = 'submit', $label = '', $options = array()) + { + $btype = 'submit'; + if(strpos($action, 'action') === 0) + { + $btype = 'button'; + } + + if(isset($options['loading']) && ($options['loading'] == false)) + { + unset($options['loading']); + $include = ''; + } + else + { + // $include = (deftrue("FONTAWESOME")) ? "data-loading-icon='fa-spinner' data-disable='true'" : ""; + $include = (deftrue("FONTAWESOME")) ? "data-loading-icon='fa-spinner' " : ""; // data-disable breaks db.php charset Fix. + } + + $confirmation = LAN_JSCONFIRM; + + if(!empty($options['confirm'])) + { + $confirmation = $options['confirm']; + } + + $options = $this->format_options('admin_button', $name, $options); + + $options['class'] = vartrue($options['class']); + $options['class'] .= ' btn ' . $action; + + if(empty($label)) + { + $label = $value; + } + + // Ability to use any kind of button class for the selected action. + if (!$this->defaultButtonClassExists($options['class'])) + { + $options['class'] .= ' ' . $this->getDefaultButtonClassByAction($action); + } + + switch ($action) + { + case 'checkall': + $options['class'] .= ' btn-mini btn-xs'; + break; + + case 'delete': + case 'danger': + + + + $options['other'] = 'data-confirm="'.$confirmation.'"'; + break; + + case 'batch': + case 'batch e-hide-if-js': + // FIXME hide-js shouldn't be here. + break; + + case 'filter': + case 'filter e-hide-if-js': + $options['class'] = 'btn btn-default'; + break; + } + + return ""; + } + + /** + * Helper function to check if a (CSS) class already contains a button class? + * + * @param string $class + * The class we want to check. + * + * @return bool + * True if $class already contains a button class. Otherwise false. + */ + function defaultButtonClassExists($class = '') + { + // Bootstrap button classes. + // @see http://getbootstrap.com/css/#buttons-options + $btnClasses = array( + 'btn-default', + 'btn-primary', + 'btn-success', + 'btn-info', + 'btn-warning', + 'btn-danger', + 'btn-link', + ); + + foreach($btnClasses as $btnClass) { + if(strpos($class, $btnClass, 0) !== false) + { + return true; + } + } + + return false; + } + + + + + + + /** + * Helper function to get default button class by action. + * + * @param string $action + * Action for a button. See button(). + * + * @return string $class + * Default button class. + */ + function getDefaultButtonClassByAction($action) + { + switch($action) + { + case 'update': + case 'create': + case 'import': + case 'submit': + case 'success': + $class = 'btn-success'; + break; + + case 'checkall': + $class = 'btn-default'; + break; + + case 'cancel': + $class = 'btn-default'; + break; + + case 'delete': + case 'danger': + $class = 'btn-danger'; + break; + + case 'execute': + $class = 'btn-success'; + break; + + case 'other': + case 'login': + case 'primary': + $class = 'btn-primary'; + break; + + case 'warning': + case 'confirm': + $class = 'btn-warning'; + break; + + case 'batch': + case 'batch e-hide-if-js': + $class = 'btn-primary'; + break; + + case 'filter': + case 'filter e-hide-if-js': + $class = 'btn-primary'; + break; + + case 'default': + default: + $class = 'btn-default'; + break; + } + + return $class; + } + + function getNext() + { + if(!$this->_tabindex_enabled) return 0; + $this->_tabindex_counter += 1; + return $this->_tabindex_counter; + } + + function getCurrent() + { + if(!$this->_tabindex_enabled) return 0; + return $this->_tabindex_counter; + } + + function resetTabindex($reset = 0) + { + $this->_tabindex_counter = $reset; + } + + function get_attributes($options, $name = '', $value = '') + { + $ret = ''; + // + foreach ($options as $option => $optval) + { + $optval = trim($optval); + switch ($option) + { + + case 'id': + $ret .= $this->_format_id($optval, $name, $value); + break; + + case 'class': + if(!empty($optval)) $ret .= " class='{$optval}'"; + break; + + case 'size': + if($optval) $ret .= " size='{$optval}'"; + break; + + case 'title': + if($optval) $ret .= " title='{$optval}'"; + break; + + case 'label': + if($optval) $ret .= " label='{$optval}'"; + break; + + case 'tabindex': + if($optval) $ret .= " tabindex='{$optval}'"; + elseif(false === $optval || !$this->_tabindex_enabled) break; + else + { + $this->_tabindex_counter += 1; + $ret .= " tabindex='".$this->_tabindex_counter."'"; + } + break; + + case 'readonly': + if($optval) $ret .= " readonly='readonly'"; + break; + + case 'multiple': + if($optval) $ret .= " multiple='multiple'"; + break; + + case 'selected': + if($optval) $ret .= " selected='selected'"; + break; + + case 'maxlength': + if($optval) $ret .= " maxlength='{$optval}'"; + break; + + case 'checked': + if($optval) $ret .= " checked='checked'"; + break; + + case 'disabled': + if($optval) $ret .= " disabled='disabled'"; + break; + + case 'required': + if($optval) $ret .= " required='required'"; + break; + + case 'autofocus': + if($optval) $ret .= " autofocus='autofocus'"; + break; + + case 'placeholder': + if($optval) { + $optval = deftrue($optval, $optval); + $ret .= " placeholder='{$optval}'"; + } + break; + + case 'wrap': + if($optval) $ret .= " wrap='{$optval}'"; + break; + + case 'autocomplete': + if($optval) $ret .= " autocomplete='{$optval}'"; + break; + + case 'pattern': + if($optval) $ret .= " pattern='{$optval}'"; + break; + + case 'other': + if($optval) $ret .= " $optval"; + break; + } + + if(substr($option,0,5) =='data-') + { + $ret .= " ".$option."='{$optval}'"; + } + + } + + return $ret; + } + + /** + * Auto-build field attribute id + * + * @param string $id_value value for attribute id passed with the option array + * @param string $name the name attribute passed to that field + * @param unknown_type $value the value attribute passed to that field + * @return string formatted id attribute + */ + function _format_id($id_value, $name, $value = '', $return_attribute = 'id') + { + if($id_value === false) return ''; + + //format data first + $name = trim($this->name2id($name), '-'); + $value = trim(preg_replace('#[^a-zA-Z0-9\-]#','-', $value), '-'); + //$value = trim(preg_replace('#[^a-z0-9\-]#/i','-', $value), '-'); // This should work - but didn't for me! + $value = trim(str_replace("/","-",$value), '-'); // Why? + if(!$id_value && is_numeric($value)) $id_value = $value; + + // clean - do it better, this could lead to dups + $id_value = trim($id_value, '-'); + + if(empty($id_value) ) return " {$return_attribute}='{$name}".($value ? "-{$value}" : '')."'";// also useful when name is e.g. name='my_name[some_id]' + elseif(is_numeric($id_value) && $name) return " {$return_attribute}='{$name}-{$id_value}'";// also useful when name is e.g. name='my_name[]' + else return " {$return_attribute}='{$id_value}'"; + } + + function name2id($name) + { + $name = strtolower($name); + return rtrim(str_replace(array('[]', '[', ']', '_', '/', ' ','.', '(', ')', '::', ':'), array('-', '-', '', '-', '-', '-', '-','','','-',''), $name), '-'); + } + + /** + * Format options based on the field type, + * merge with default + * + * @param string $type + * @param string $name form name attribute value + * @param array|string $user_options + * @return array merged options + */ + function format_options($type, $name, $user_options=null) + { + if(is_string($user_options)) + { + parse_str($user_options, $user_options); + } + + $def_options = $this->_default_options($type); + + + if(is_array($user_options)) + { + $user_options['name'] = $name; //required for some of the automated tasks + + foreach (array_keys($user_options) as $key) + { + if(!isset($def_options[$key]) && substr($key,0,5)!='data-') unset($user_options[$key]); // data-xxxx exempt //remove it? + } + } + else + { + $user_options = array('name' => $name); //required for some of the automated tasks + } + + return array_merge($def_options, $user_options); + } + + /** + * Get default options array based on the field type + * + * @param string $type + * @return array default options + */ + function _default_options($type) + { + if(isset($this->_cached_attributes[$type])) return $this->_cached_attributes[$type]; + + $def_options = array( + 'id' => '', + 'class' => '', + 'title' => '', + 'size' => '', + 'readonly' => false, + 'selected' => false, + 'checked' => false, + 'disabled' => false, + 'required' => false, + 'autofocus' => false, + 'tabindex' => 0, + 'label' => '', + 'placeholder' => '', + 'pattern' => '', + 'other' => '', + 'autocomplete' => '', + 'maxlength' => '', + 'wrap' => '', + 'multiple' => '', + + // 'multiple' => false, - see case 'select' + ); + + $form_control = (THEME_LEGACY !== true) ? ' form-control' : ''; + + switch ($type) { + case 'hidden': + $def_options = array('id' => false, 'disabled' => false, 'other' => ''); + break; + + case 'text': + $def_options['class'] = 'tbox input-text'.$form_control; + unset($def_options['selected'], $def_options['checked']); + break; + + case 'number': + $def_options['class'] = 'tbox '.$form_control; + break; + + case 'file': + $def_options['class'] = 'tbox file'; + unset($def_options['selected'], $def_options['checked']); + break; + + case 'textarea': + $def_options['class'] = 'tbox textarea'.$form_control; + unset($def_options['selected'], $def_options['checked'], $def_options['size']); + break; + + case 'select': + $def_options['class'] = 'tbox select'.$form_control; + $def_options['multiple'] = false; + unset($def_options['checked']); + break; + + case 'option': + $def_options = array('class' => '', 'selected' => false, 'other' => '', 'disabled' => false, 'label' => ''); + break; + + case 'radio': + //$def_options['class'] = ' '; + $def_options = array('class' => '', 'id'=>''); + unset($def_options['size'], $def_options['selected']); + break; + + case 'checkbox': + unset($def_options['size'], $def_options['selected']); + break; + + case 'submit': + $def_options['class'] = 'button btn btn-primary'; + unset($def_options['checked'], $def_options['selected'], $def_options['readonly']); + break; + + case 'submit_image': + $def_options['class'] = 'action'; + unset($def_options['checked'], $def_options['selected'], $def_options['readonly']); + break; + + case 'admin_button': + unset($def_options['checked'], $def_options['selected'], $def_options['readonly']); + break; + + } + + $this->_cached_attributes[$type] = $def_options; + return $def_options; + } + + function columnSelector($columnsArray, $columnsDefault = '', $id = 'column_options') + { + $columnsArray = array_filter($columnsArray); + + // navbar-header nav-header + // navbar-header nav-header + $text = '"; + + // $text .= "
"; + + $text .= ""; + + + /* + $text = ''; + */ + return $text; + } + + + + + + + + + + + + function colGroup($fieldarray, $columnPref = '') + { + $text = ""; + $count = 0; + foreach($fieldarray as $key=>$val) + { + if ((in_array($key, $columnPref) || $key=='options' || vartrue($val['forced'])) && !vartrue($val['nolist'])) + { + + $class = vartrue($val['class']) ? 'class="'.$val['class'].'"' : ''; + $width = vartrue($val['width']) ? ' style="width:'.$val['width'].'"' : ''; + $text .= ' + '; + $count++; + } + } + + return ' + + '.$text.' + + '; + } + + function thead($fieldarray, $columnPref = array(), $querypattern = '', $requeststr = '') + { + $text = ""; + + $querypattern = filter_var($querypattern, FILTER_SANITIZE_STRING); + if(!$requeststr) $requeststr = rawurldecode(e_QUERY); + $requeststr = filter_var($requeststr, FILTER_SANITIZE_STRING); + + // Recommended pattern: mode=list&field=[FIELD]&asc=[ASC]&from=[FROM] + if(strpos($querypattern,'&')!==FALSE) + { + // we can assume it's always $_GET since that's what it will generate + // more flexible (e.g. pass default values for order/field when they can't be found in e_QUERY) & secure + $tmp = str_replace('&', '&', $requeststr ? $requeststr : e_QUERY); + parse_str($tmp, $tmp); + + $etmp = array(); + parse_str(str_replace('&', '&', $querypattern), $etmp); + } + else // Legacy Queries. eg. main.[FIELD].[ASC].[FROM] + { + $tmp = explode(".", ($requeststr ? $requeststr : e_QUERY)); + $etmp = explode(".", $querypattern); + } + + foreach($etmp as $key => $val) // I'm sure there's a more efficient way to do this, but too tired to see it right now!. + { + if($val == "[FIELD]") + { + $field = varset($tmp[$key]); + } + + if($val == "[ASC]") + { + $ascdesc = varset($tmp[$key]); + } + if($val == "[FROM]") + { + $fromval = varset($tmp[$key]); + } + } + + if(!varset($fromval)){ $fromval = 0; } + + $sorted = varset($ascdesc); + $ascdesc = ($sorted == 'desc') ? 'asc' : 'desc'; + + foreach($fieldarray as $key=>$val) + { + if ((in_array($key, $columnPref) || ($key === 'options' && isset($val['title'])) || (vartrue($val['forced']))) && !vartrue($val['nolist'])) + { + $cl = (vartrue($val['thclass'])) ? " class='".$val['thclass']."'" : ""; + + $aClass = ($key === $field) ? "class='sorted-".$sorted."'" : ""; + + $text .= " + + "; + + if($querypattern!="" && !vartrue($val['nosort']) && $key != "options" && $key != "checkboxes") + { + $from = ($key == $field) ? $fromval : 0; + $srch = array("[FIELD]","[ASC]","[FROM]"); + $repl = array($key,$ascdesc,$from); + $val['url'] = e_SELF."?".str_replace($srch,$repl,$querypattern); + } + + + + $text .= (vartrue($val['url'])) ? "" : ""; // Really this column-sorting link should be auto-generated, or be autocreated via unobtrusive js. + $text .= defset($val['title'], $val['title']); + $text .= ($val['url']) ? "" : ""; + $text .= ($key === "options" && !vartrue($val['noselector'])) ? $this->columnSelector($fieldarray, $columnPref) : ""; + $text .= ($key === "checkboxes") ? $this->checkbox_toggle('e-column-toggle', vartrue($val['toggle'], 'multiselect')) : ""; + + + $text .= " + + "; + } + } + + return " + + ".$text." + + "; + + } + + + /** + * Render Table cells from hooks. + * @param array $data + * @return string + */ + function renderHooks($data) + { + $hooks = e107::getEvent()->triggerHook($data); + + $text = ""; + + if(!empty($hooks)) + { + foreach($hooks as $plugin => $hk) + { + $text .= "\n\n\n"; + + if(!empty($hk)) + { + foreach($hk as $hook) + { + $text .= "\t\t\t\n"; + $text .= "\t\t\t".$hook['caption']."\n"; + $text .= "\t\t\t".$hook['html'].""; + $text .= (varset($hook['help'])) ? "\n".$hook['help']."" : ""; + $text .= "\n\t\t\t\n"; + } + + + } + } + } + + return $text; + } + + + + + /** + * Render Related Items for the current page/news-item etc. + * @param string $type : comma separated list. ie. plugin folder names. + * @param string $tags : comma separated list of keywords to return related items of. + * @param array $curVal. eg. array('page'=> current-page-id-value); + */ + function renderRelated($parm,$tags, $curVal, $template=null) //XXX TODO Cache! + { + + if(empty($tags)) + { + return; + } + + $tags = str_replace(', ',',', $tags); //BC Fix, all tags should be comma separated without spaces ie. one,two NOT one, two + + e107::setRegistry('core/form/related',$tags); // TODO Move to elsewhere so it works without rendering? e107::related() set and get by plugins? + + if(!varset($parm['limit'])) + { + $parm = array('limit' => 5); + } + + if(!varset($parm['types'])) + { + $parm['types'] = 'news'; + } + + if(empty($template)) + { + $TEMPLATE['start'] = "

".defset('LAN_RELATED', 'Related')."

"; + + } + else + { + $TEMPLATE = $template; + } + + + + $tp = e107::getParser(); + + $types = explode(',',$parm['types']); + $list = array(); + + $head = $tp->parseTemplate($TEMPLATE['start'],true); + + foreach($types as $plug) + { + + if(!$obj = e107::getAddon($plug,'e_related')) + { + continue; + } + + $parm['current'] = intval(varset($curVal[$plug])); + + + + + $tmp = $obj->compile($tags,$parm); + + if(count($tmp)) + { + foreach($tmp as $val) + { + + $row = array( + 'RELATED_URL' => $tp->replaceConstants($val['url'],'full'), + 'RELATED_TITLE' => $val['title'], + 'RELATED_IMAGE' => $tp->toImage($val['image']), + 'RELATED_SUMMARY' => $tp->toHTML($val['summary'],true,'BODY') + ); + + $list[] = $tp->simpleParse($TEMPLATE['item'], $row); + + } + } + } + + if(count($list)) + { + return ""; + + // return ""; //XXX Tablerender? + } + + } + + + + /** + * Render Table cells from field listing. + * @param array $fieldarray - eg. $this->fields + * @param array $currentlist - eg $this->fieldpref + * @param array $fieldvalues - eg. $row + * @param string $pid - eg. table_id + * @return string + */ + function renderTableRow($fieldarray, $currentlist, $fieldvalues, $pid) + { + $cnt = 0; + $ret = ''; + + /*$fieldarray = $obj->fields; + $currentlist = $obj->fieldpref; + $pid = $obj->pid;*/ + + $trclass = vartrue($fieldvalues['__trclass']) ? ' class="'.$trclass.'"' : ''; + unset($fieldvalues['__trclass']); + + foreach ($fieldarray as $field => $data) + { + + + // shouldn't happen... test with Admin->Users with user_xup visible and NULL values in user_xup table column before re-enabling this code. + /* + if(!isset($fieldvalues[$field]) && vartrue($data['alias'])) + { + $fieldvalues[$data['alias']] = $fieldvalues[$data['field']]; + $field = $data['alias']; + } + */ + + //Not found + if((!varset($data['forced']) && !in_array($field, $currentlist)) || varset($data['nolist'])) + { + continue; + } + elseif(vartrue($data['type']) != 'method' && !$data['forced'] && !isset($fieldvalues[$field]) && $fieldvalues[$field] !== NULL) + { + $ret .= " + + Not Found! ($field) + + "; + + continue; + } + + $tdclass = vartrue($data['class']); + + if($field == 'checkboxes') $tdclass = $tdclass ? $tdclass.' autocheck e-pointer' : 'autocheck e-pointer'; + + if($field == 'options') $tdclass = $tdclass ? $tdclass.' options' : 'options'; + + + + // there is no other way for now - prepare user data + if('user' == vartrue($data['type']) /* && isset($data['readParms']['idField'])*/) + { + if(varset($data['readParms']) && is_string($data['readParms'])) parse_str($data['readParms'], $data['readParms']); + if(isset($data['readParms']['idField'])) + { + $data['readParms']['__idval'] = $fieldvalues[$data['readParms']['idField']]; + } + elseif(isset($fieldvalues['user_id'])) // Default + { + $data['readParms']['__idval'] = $fieldvalues['user_id']; + } + + if(isset($data['readParms']['nameField'])) + { + $data['readParms']['__nameval'] = $fieldvalues[$data['readParms']['nameField']]; + } + elseif(isset($fieldvalues['user_name'])) // Default + { + $data['readParms']['__nameval'] = $fieldvalues['user_name']; + } + + + } + $value = $this->renderValue($field, varset($fieldvalues[$field]), $data, varset($fieldvalues[$pid])); + + + + if($tdclass) + { + $tdclass = ' class="'.$tdclass.'"'; + } + $ret .= ' + + '.$value.' + + '; + + $cnt++; + } + + if($cnt) + { + return ' + + '.$ret.' + + '; + } + + return ''; + } + + /** + * Inline Token + * @return string + */ + private function inlineToken() + { + $this->_inline_token = $this->_inline_token ?: + password_hash(session_id(), PASSWORD_DEFAULT, ['cost' => 04]); + return $this->_inline_token; + } + + /** + * Create an Inline Edit link. + * @param string $dbField : field being edited + * @param int $pid : primary ID of the row being edited. + * @param string $fieldName - Description of the field name (caption) + * @param mixed $curVal : existing value of in the field + * @param mixed $linkText : existing value displayed + * @param string $type text|textarea|select|date|checklist + * @param array $array : array data used in dropdowns etc. + */ + public function renderInline($dbField, $pid, $fieldName, $curVal, $linkText, $type='text', $array=null, $options=array()) + { + $jsonArray = array(); + + if(!empty($array)) + { + foreach($array as $k=>$v) + { + $jsonArray[$k] = str_replace("'", "`", $v); + } + } + + $source = e107::getParser()->toJSON($jsonArray, true); + + $mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); + + if(!isset($options['url'])) + { + $options['url'] = e_SELF."?mode={$mode}&action=inline&id={$pid}&ajax_used=1"; + } + + if(!empty($pid)) + { + $options['pk'] = $pid; + } + + $title = varset($options['title'] , (LAN_EDIT." ".$fieldName)); + $class = varset($options['class'] ,''); + + unset( $options['title']); + + $text = "inlineToken(); + + if(!empty($options)) + { + foreach($options as $k=>$opt) + { + if(!empty($opt)) + { + $text .= " data-".$k."='".$opt."'"; + } + } + } + + $text .= ">".$linkText.""; + + return $text; + } + + /** + * Check if a value should be linked and wrap in tag if required. + * @todo global pref for the target option? + * @param mixed $value + * @param array $parms + * @param $id + * @return string + */ + private function renderLink($value, $parms, $id=null) + { + if(empty($parms['link']) && empty($parms['url'])) + { + return $value; + } + + $dialog = vartrue($parms['target']) =='dialog' ? " e-modal" : ""; // iframe + $ext = vartrue($parms['target']) =='blank' ? " rel='external' " : ""; // new window + $modal = vartrue($parms['target']) =='modal' ? " data-toggle='modal' data-cache='false' data-target='#uiModal' " : ""; + + + if(!empty($parms['url'])) // ie. use e_url.php + { + $plugin = $this->getController()->getPluginName(); + $data = $this->getController()->getListModel()->getData(); + $link = e107::url($plugin,$parms['url'],$data); + } + else // old way. + { + $tp = e107::getParser(); + + $link = str_replace('[id]',$id,$parms['link']); + $link = $tp->replaceConstants($link); // SEF URL is not important since we're in admin. + + + if($parms['link'] === 'sef' && $this->getController()->getListModel()) + { + $model = $this->getController()->getListModel(); + + if(!$model->getUrl()) + { + $model->setUrl($this->getController()->getUrl()); + } + // assemble the url + $link = $model->url(null); + } + elseif(!empty($data[$parms['link']])) // support for a field-name as the link. eg. link_url. + { + $data = $this->getController()->getListModel()->getData(); + $link = $tp->replaceConstants(vartrue($data[$parms['link']])); + } + } + // in case something goes wrong... + if($link) + { + return "".$value.""; + } + + return $value; + + } + + private function renderOptions($parms, $value='', $id, $attributes) + { + $tp = e107::getParser(); + $cls = false; + + $editIconDefault = deftrue('ADMIN_EDIT_ICON', $tp->toGlyph('fa-edit')); + $deleteIconDefault = deftrue('ADMIN_DELETE_ICON', $tp->toGlyph('fa-trash')); +/* + if($attributes['grid']) + { + $editIconDefault = $tp->toGlyph('fa-edit'); + $deleteIconDefault = $tp->toGlyph('fa-trash'); + } +*/ + + $sf = $this->getController()->getSortField(); + + if(!isset($parms['sort']) && !empty($sf)) + { + $parms['sort'] = true; + } + + $value = "
"; + + if(!empty($parms['sort']) && empty($attributes['grid'])) + { + $mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); + $from = intval(vartrue($_GET['from'],0)); + $value .= "".ADMIN_SORT_ICON." "; + } + + + if(varset($parms['editClass'])) + { + $cls = (deftrue($parms['editClass'])) ? constant($parms['editClass']) : $parms['editClass']; + } + + if((false === $cls || check_class($cls)) && varset($parms['edit'],1) == 1) + { + + parse_str(str_replace('&', '&', e_QUERY), $query); //FIXME - FIX THIS + // keep other vars in tact + $query['action'] = 'edit'; + $query['id'] = $id; + + + if(!empty($parms['target']) && $parms['target']=='modal') + { + $eModal = " e-modal "; + $eModalCap = !empty($parms['modalCaption']) ? "data-modal-caption='".$parms['modalCaption']."'" : "data-modal-caption='#".$id."'"; + $query['iframe'] = 1; + } + else + { + $eModal = ""; + $eModalCap = ""; + } + + if(!empty($parms['modalSubmit'])) + { + $eModalCap .= " data-modal-submit='true'"; + } + + $query = http_build_query($query, null, '&'); + $value .= " + ".$editIconDefault.""; + } + + $delcls = !empty($attributes['noConfirm']) ? ' no-confirm' : ''; + if(varset($parms['deleteClass']) && varset($parms['delete'],1) == 1) + { + $cls = (deftrue($parms['deleteClass'])) ? constant($parms['deleteClass']) : $parms['deleteClass']; + + if(check_class($cls)) + { + $parms['class'] = 'action delete btn btn-default'.$delcls; + unset($parms['deleteClass']); + $parms['icon'] = $deleteIconDefault; + $value .= $this->submit_image('etrigger_delete['.$id.']', $id, 'delete', LAN_DELETE.' [ ID: '.$id.' ]', $parms); + } + } + else + { + $parms['class'] = 'action delete btn btn-default'.$delcls; + $parms['icon'] = $deleteIconDefault; + $value .= $this->submit_image('etrigger_delete['.$id.']', $id, 'delete', LAN_DELETE.' [ ID: '.$id.' ]', $parms); + } + + //$attributes['type'] = 'text'; + $value .= "
"; + + return $value; + + } + + /** + * Render Field Value + * @param string $field field name + * @param mixed $value field value + * @param array $attributes field attributes including render parameters, element options - see e_admin_ui::$fields for required format + * @return string + */ + function renderValue($field, $value, $attributes, $id = 0) + { + + + if(!empty($attributes['multilan']) && is_array($value)) + { + $value = varset($value[e_LANGUAGE],''); + } + + $parms = array(); + if(isset($attributes['readParms'])) + { + if(!is_array($attributes['readParms'])) parse_str($attributes['readParms'], $attributes['readParms']); + $parms = $attributes['readParms']; + } + + // @see custom fields in cpage which accept json params. + if(!empty($attributes['writeParms']) && $tmpOpt = e107::getParser()->isJSON($attributes['writeParms'])) + { + $attributes['writeParms'] = $tmpOpt; + unset($tmpOpt); + } + + + + if(!empty($attributes['inline'])) $parms['editable'] = true; // attribute alias + if(!empty($attributes['sort'])) $parms['sort'] = true; // attribute alias + + if(!empty($parms['type'])) // Allow the use of a different type in readMode. eg. type=method. + { + $attributes['type'] = $parms['type']; + } + + + + + $this->renderValueTrigger($field, $value, $parms, $id); + + $tp = e107::getParser(); + switch($field) // special fields + { + case 'options': + + if(!empty($attributes['type']) && ($attributes['type'] == "method")) // Allow override with 'options' function. + { + $attributes['mode'] = "read"; + if(isset($attributes['method']) && $attributes['method'] && method_exists($this, $attributes['method'])) + { + $method = $attributes['method']; + return $this->$method($parms, $value, $id, $attributes); + + } + elseif(method_exists($this, 'options')) + { + //return $this->options($field, $value, $attributes, $id); + // consistent method arguments, fixed in admin cron administration + $attributes['type'] = null; // prevent infinite loop. + + return $this->options($parms, $value, $id, $attributes); + } + } + + if(!$value) + { + $value = $this->renderOptions($parms, $value, $id, $attributes); + } + + return $value; + break; + + case 'checkboxes': + + //$attributes['type'] = 'text'; + if(empty($attributes['writeParms'])) // avoid comflicts with a field called 'checkboxes' + { + $value = $this->checkbox(vartrue($attributes['toggle'], 'multiselect').'['.$id.']', $id); + return $value; + } + + + break; + } + + switch($attributes['type']) + { + case 'number': + if(!$value) $value = '0'; + + if($parms) + { + if(!isset($parms['sep'])) $value = number_format($value, varset($parms['decimals'],0)); + else $value = number_format($value, $parms['decimals'], vartrue($parms['point'], '.'), vartrue($parms['sep'], ' ')); + } + + if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up + { + $value = $this->renderInline($field,$id,$attributes['title'],$value, $value); + } + elseif(!empty($parms['link'])) + { + $value = $this->renderLink($value,$parms,$id); + } + + + $value = vartrue($parms['pre']).$value.vartrue($parms['post']); + // else same + break; + + case 'country': + + $_value = $this->getCountry($value); + + if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up + { + $arr = $this->getCountry(); + $value = $this->renderInline($field,$id,$attributes['title'],$value, $_value, 'select', $arr); + } + else + { + $value = $_value; + } + + break; + + case 'ip': + //$e107 = e107::getInstance(); + $value = "".e107::getIPHandler()->ipDecode($value).'';; + // else same + break; + + case 'templates': + case 'layouts': + + if(!empty($attributes['writeParms'])) + { + if(is_string($attributes['writeParms'])) parse_str($attributes['writeParms'], $attributes['writeParms']); + } + + if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up + { + $wparms = $attributes['writeParms']; + + $location = vartrue($wparms['plugin']); // empty - core + $ilocation = vartrue($wparms['id'], $location); // omit if same as plugin name + $where = vartrue($wparms['area'], 'front'); //default is 'front' + $filter = varset($wparms['filter']); + $merge = isset($wparms['merge']) ? (bool) $wparms['merge'] : true; + + $layouts = e107::getLayouts($location, $ilocation, $where, $filter, $merge, false); + + $label = varset($layouts[$value], $value); + + $value = $this->renderInline($field, $id, $attributes['title'], $value, $label, 'select', $layouts); + } + + $value = vartrue($parms['pre']) . $value . vartrue($parms['post']); + break; + + case 'checkboxes': + case 'comma': + case 'dropdown': + // XXX - should we use readParams at all here? see writeParms check below + + if($parms && is_array($parms)) // FIXME - add support for multi-level arrays (option groups) + { + //FIXME return no value at all when 'editable=1' is a readParm. See FAQs templates. + // $value = vartrue($parms['pre']).vartrue($parms[$value]).vartrue($parms['post']); + // break; + } + + // NEW - multiple (array values) support + // FIXME - add support for multi-level arrays (option groups) + if(!is_array($attributes['writeParms'])) parse_str($attributes['writeParms'], $attributes['writeParms']); + $wparms = $attributes['writeParms']; + + if(!is_array(varset($wparms['__options']))) parse_str($wparms['__options'], $wparms['__options']); + + if(!empty($wparms['optArray'])) + { + $fopts = $wparms; + $wparms = $fopts['optArray']; + unset($fopts['optArray']); + $wparms['__options'] = $fopts; + } + + + $opts = $wparms['__options']; + unset($wparms['__options']); + $_value = $value; + + if($attributes['type'] == 'checkboxes' || $attributes['type'] == 'comma') + { + $opts['multiple'] = true; + } + + if(!empty($opts['multiple'])) + { + $ret = array(); + $value = is_array($value) ? $value : explode(',', $value); + foreach ($value as $v) + { + if(isset($wparms[$v])) $ret[] = $wparms[$v]; + } + $value = implode(', ', $ret); + + + } + else + { + $ret = ''; + if(isset($wparms[$value])) $ret = $wparms[$value]; + $value = $ret; + } + + $value = ($value ? vartrue($parms['pre']).defset($value, $value).vartrue($parms['post']) : ''); + + if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up + { + $xtype = ($attributes['type'] == 'dropdown') ? 'select' : 'checklist'; + $value = $this->renderInline($field, $id, $attributes['title'], $_value, $value, $xtype, $wparms); + } + + // return ; + break; + + case 'radio': + + + if($parms && isset($parms[$value])) // FIXME - add support for multi-level arrays (option groups) + { + $value = vartrue($parms['pre']).vartrue($parms[$value]).vartrue($parms['post']); + break; + } + + if(!is_array($attributes['writeParms'])) parse_str($attributes['writeParms'], $attributes['writeParms']); + + if(!empty($attributes['writeParms']['optArray'])) + { + $radioValue = $attributes['writeParms']['optArray'][$value]; + + if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up + { + $radioValue = $this->renderInline($field, $id, $attributes['title'], $value, $radioValue, 'select', $attributes['writeParms']['optArray']); + } + } + else + { + $radioValue = vartrue($attributes['writeParms'][$value]); + } + + + $value = vartrue($attributes['writeParms']['__options']['pre']).$radioValue.vartrue($attributes['writeParms']['__options']['post']); + break; + + case 'tags': + if(!empty($parms['constant'])) + { + $value = defset($value, $value); + } + + if(!empty($parms['truncate'])) + { + $value = $tp->text_truncate($value, $parms['truncate'], '...'); + } + elseif(!empty($parms['htmltruncate'])) + { + $value = $tp->html_truncate($value, $parms['htmltruncate'], '...'); + } + if(!empty($parms['wrap'])) + { + $value = $tp->htmlwrap($value, (int) $parms['wrap'], varset($parms['wrapChar'], ' ')); + } + + $value = $this->renderLink($value,$parms,$id); + /* + if(!empty($parms['link']) && $id) + { + $link = str_replace('[id]', $id, $parms['link']); + $link = $tp->replaceConstants($link); // SEF URL is not important since we're in admin. + + $dialog = vartrue($parms['target']) == 'dialog' ? " e-dialog" : ""; // iframe + $ext = vartrue($parms['target']) == 'blank' ? " rel='external' " : ""; // new window + $modal = vartrue($parms['target']) == 'modal' ? " data-toggle='modal' data-cache='false' data-target='#uiModal' " : ""; + + if($parms['link'] == 'sef' && $this->getController()->getListModel()) + { + $model = $this->getController()->getListModel(); + // copy url config + if(!$model->getUrl()) + { + $model->setUrl($this->getController()->getUrl()); + } + // assemble the url + $link = $model->url(); + } + + elseif(vartrue($data[$parms['link']])) // support for a field-name as the link. eg. link_url. + { + $link = $tp->replaceConstants(vartrue($data[$parms['link']])); + } + + // in case something goes wrong... + if($link) + { + $value = "" . $value . ""; + } + }*/ + + if(empty($value)) + { + $value = '-'; + $setValue = "data-value=''"; + } + else + { + $setValue = ""; + + if($attributes['type'] == 'tags' && !empty($value)) + { + $setValue = "data-value='" . $value . "'"; + $value = str_replace(",", ", ", $value); // add spaces so it wraps, but don't change the actual values. + } + } + + + if(!vartrue($attributes['noedit']) && vartrue($parms['editable']) && !vartrue($parms['link'])) // avoid bad markup, better solution coming up + { + $options['selectize'] = array( + 'create' => true, + 'maxItems' => vartrue($parms['maxItems'], 7), + 'mode' => 'multi', + 'e_editable' => $field . '_' . $id, + ); + + $tpl = $this->text($field, $value, 80, $options); + + $mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); + $value = "" . $value . ""; + } + + $value = vartrue($parms['pre']) . $value . vartrue($parms['post']); + break; + + case 'text': + + if(!empty($parms['constant'])) + { + $value = defset($value,$value); + } + + if(vartrue($parms['truncate'])) + { + $value = $tp->text_truncate($value, $parms['truncate'], '...'); + } + elseif(vartrue($parms['htmltruncate'])) + { + $value = $tp->html_truncate($value, $parms['htmltruncate'], '...'); + } + if(vartrue($parms['wrap'])) + { + $value = $tp->htmlwrap($value, (int)$parms['wrap'], varset($parms['wrapChar'], ' ')); + } + + $value = $this->renderLink($value,$parms,$id); + + /* + if(vartrue($parms['link']) && $id) + { + $link = str_replace('[id]',$id,$parms['link']); + $link = $tp->replaceConstants($link); // SEF URL is not important since we're in admin. + + $dialog = vartrue($parms['target']) =='dialog' ? " e-dialog" : ""; // iframe + $ext = vartrue($parms['target']) =='blank' ? " rel='external' " : ""; // new window + $modal = vartrue($parms['target']) =='modal' ? " data-toggle='modal' data-cache='false' data-target='#uiModal' " : ""; + + if($parms['link'] == 'sef' && $this->getController()->getListModel()) + { + $model = $this->getController()->getListModel(); + // copy url config + if(!$model->getUrl()) $model->setUrl($this->getController()->getUrl()); + // assemble the url + $link = $model->url(null); + } + elseif(vartrue($data[$parms['link']])) // support for a field-name as the link. eg. link_url. + { + $link = $tp->replaceConstants(vartrue($data[$parms['link']])); + } + + // in case something goes wrong... + if($link) $value = "".$value.""; + }*/ + + if(empty($value)) + { + $value = '-'; + $setValue = "data-value=''"; + } + else + { + $setValue = ""; + + if($attributes['type'] == 'tags' && !empty($value)) + { + $setValue = "data-value='".$value."'"; + $value = str_replace(",", ", ", $value); // add spaces so it wraps, but don't change the actual values. + } + } + + + if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up + { + $value = $this->renderInline($field,$id,$attributes['title'],$value, $value); + } + + $value = vartrue($parms['pre']).$value.vartrue($parms['post']); + break; + + + + case 'bbarea': + case 'textarea': + + + if($attributes['type'] == 'textarea' && !vartrue($attributes['noedit']) && vartrue($parms['editable']) && !vartrue($parms['link'])) // avoid bad markup, better solution coming up + { + return $this->renderInline($field,$id,$attributes['title'],$value,substr($value,0,50)."...",'textarea'); //FIXME. + } + + + $expand = '...'; + $toexpand = false; + if($attributes['type'] == 'bbarea' && !isset($parms['bb'])) $parms['bb'] = true; //force bb parsing for bbareas + $elid = trim(str_replace('_', '-', $field)).'-'.$id; + if(!vartrue($parms['noparse'])) $value = $tp->toHTML($value, (vartrue($parms['bb']) ? true : false), vartrue($parms['parse'])); + if(vartrue($parms['expand']) || vartrue($parms['truncate']) || vartrue($parms['htmltruncate'])) + { + $ttl = vartrue($parms['expand']); + if($ttl == 1) + { + $dataAttr = "data-text-more='" . LAN_MORE . "' data-text-less='" . LAN_LESS . "'"; + $ttl = $expand.""; + } + + $expands = ''.defset($ttl, $ttl).""; + } + + $oldval = $value; + if(vartrue($parms['truncate'])) + { + $value = $oldval = strip_tags($value); + $value = $tp->text_truncate($value, $parms['truncate'], ''); + $toexpand = $value != $oldval; + } + elseif(vartrue($parms['htmltruncate'])) + { + $value = $tp->html_truncate($value, $parms['htmltruncate'], ''); + $toexpand = $value != $oldval; + } + if($toexpand) + { + // force hide! TODO - core style .expand-c (expand container) + $value .= ''; + $value .= varset($expands); // 'More..' button. Keep it at the bottom so it does't cut the sentence. + } + + + + break; + + case 'icon': + + $value = "".$tp->toIcon($value,$parms).""; + + break; + + case 'file': + if(vartrue($parms['base'])) + { + $url = $parms['base'].$value; + } + else $url = e107::getParser()->replaceConstants($value, 'full'); + $name = basename($value); + $value = ''.$name.''; + break; + + case 'image': //js tooltip... + + $thparms = array(); + $createLink = true; + + // Support readParms example: thumb=1&w=200&h=300 + // Support readParms example: thumb=1&aw=80&ah=30 + if(isset($parms['h'])) { $thparms['h'] = intval($parms['h']); } + if(isset($parms['ah'])) { $thparms['ah'] = intval($parms['ah']); } + if(isset($parms['w'])) { $thparms['w'] = intval($parms['w']); } + if(isset($parms['aw'])) { $thparms['aw'] = intval($parms['aw']); } + if(isset($parms['crop'])) { $thparms['crop'] = $parms['crop']; } + + + + if($value) + { + + if(strpos($value,",")!==false) + { + $tmp = explode(",",$value); + $value = $tmp[0]; + unset($tmp); + } + + if(empty($parms['thumb_aw']) && !empty($parms['thumb']) && strpos($parms['thumb'],'x')!==false) + { + list($parms['thumb_aw'],$parms['thumb_ah']) = explode('x',$parms['thumb']); + } + + $vparm = array('thumb'=>'tag','w'=> vartrue($parms['thumb_aw'],'80')); + + if($video = e107::getParser()->toVideo($value,$vparm)) + { + return $video; + } + + $fileOnly = basename($value); + // Not an image but a file. (media manager) + if(!preg_match("/\.(png|jpg|jpeg|gif|PNG|JPG|JPEG|GIF)$/", $fileOnly) && false !== strpos($fileOnly,'.')) + { + $icon = "{e_IMAGE}filemanager/zip_32.png"; + $src = $tp->replaceConstants(vartrue($parms['pre']).$icon, 'abs'); + // return $value; + return e107::getParser()->toGlyph('fa-file','size=2x'); + // return ''.$value.''; + } + + + + if(!empty($parms['thumb'])) + { + + if(isset($parms['link']) && empty($parms['link'])) + { + $createLink = false; + } + + // Support readParms example: thumb=200x300 (wxh) + if(strpos($parms['thumb'],'x')!==false) + { + list($thparms['w'],$thparms['h']) = explode('x',$parms['thumb']); + } + + // Support readParms example: thumb={width} + if(!isset($parms['w']) && is_numeric($parms['thumb']) && '1' != $parms['thumb']) + { + $thparms['w'] = intval($parms['thumb']); + } + elseif(vartrue($parms['thumb_aw'])) // Legacy v2. + { + $thparms['aw'] = intval($parms['thumb_aw']); + } + + if(!empty($parms['legacyPath'])) + { + $thparms['legacy'] = $parms['legacyPath']; + $parms['pre'] = rtrim($parms['legacyPath'],'/').'/'; + } + // return print_a($thparms,true); + + if(!empty($value[0]) && $value[0] === '{') // full path to convert. + { + $src = $tp->replaceConstants($value, 'abs'); + } + else // legacy link without {e_XXX} path. eg. downloads thumbs. + { + $src = $tp->replaceConstants(vartrue($parms['pre']).$value, 'abs'); + } + + $alt = basename($src); + + + $thparms['alt'] = $alt; + $thparms['class'] = "thumbnail e-thumb"; + + // e107::getDebug()->log($value); + + $ttl = $tp->toImage($value, $thparms); + + if($createLink === false) + { + return $ttl; + } + + + $value = ''.$ttl.''; + } + else + { + $src = $tp->replaceConstants(vartrue($parms['pre']).$value, 'abs'); + $alt = $src; //basename($value); + $ttl = vartrue($parms['title'], 'LAN_PREVIEW'); + $value = ''.defset($ttl, $ttl).''; + } + } + elseif(!empty($parms['fallback'])) + { + $value = $parms['fallback']; + $thparms['class'] = "thumbnail e-thumb fallback"; + return $tp->toImage($value, $thparms); + } + break; + + + case 'media': + return e107::getMedia()->previewTag($value, $parms); + break; + + case 'files': + $ret = '
    '; + for ($i=0; $i < 5; $i++) + { + //$k = $key.'['.$i.'][path]'; + $ival = $value[$i]['path']; + $ret .= '
  1. '.$ival.'
  2. '; + } + $ret .= '
'; + $value = $ret; + break; + + case 'datestamp': + $value = $value ? e107::getDate()->convert_date($value, vartrue($parms['mask'], 'short')) : ''; + break; + + case 'date': + + if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up + { + $value = $this->renderInline($field,$id,$attributes['title'],$value, $value); + } + + // just show original value + break; + + case 'userclass': + $dispvalue = $this->_uc->getName($value); + // Inline Editing. + if(empty($attributes['noedit']) && !empty($parms['editable']) && empty($parms['link'])) // avoid bad markup, better solution coming up + { + // $mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); + + $uc_options = vartrue($parms['classlist'], 'public,guest,nobody,member,admin,main,classes'); // defaults to 'public,guest,nobody,member,classes' (userclass handler) + unset($parms['classlist']); + + $array = e107::getUserClass()->uc_required_class_list($uc_options); //XXX Ugly looking (non-standard) function naming - TODO discuss name change. + + $value = $this->renderInline($field, $id, $attributes['title'], $value, $dispvalue, 'select', $array, array('placement'=>'left')); + } + else + { + $value = $dispvalue; + } + break; + + case 'userclasses': + // return $value; + $classes = explode(',', $value); + + $uv = array(); + foreach ($classes as $cid) + { + if(!empty($parms['defaultLabel']) && $cid === '') + { + $uv[] = $parms['defaultLabel']; + continue; + } + + $uv[] = $this->_uc->getName($cid); + } + + + + $dispvalue = implode(vartrue($parms['separator'],"
"), $uv); + + // Inline Editing. + if(!vartrue($attributes['noedit']) && vartrue($parms['editable']) && !vartrue($parms['link'])) // avoid bad markup, better solution coming up + { + $uc_options = vartrue($parms['classlist'], 'public,guest, nobody,member,admin,main,classes'); // defaults to 'public,guest,nobody,member,classes' (userclass handler) + $array = e107::getUserClass()->uc_required_class_list($uc_options); //XXX Ugly looking (non-standard) function naming - TODO discuss name change. + + //$mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); + $mode = $tp->filter(vartrue($_GET['mode'], ''),'w'); + $source = str_replace('"',"'",json_encode($array, JSON_FORCE_OBJECT)); + + //NOTE Leading ',' required on $value; so it picks up existing value. + $value = "".$dispvalue.""; + } + else + { + $value = $dispvalue; + } + + unset($parms['classlist']); + + break; + + /*case 'user_name': + case 'user_loginname': + case 'user_login': + case 'user_customtitle': + case 'user_email':*/ + case 'user': + + /*if(is_numeric($value)) + { + $value = e107::user($value); + if($value) + { + $value = $value[$attributes['type']] ? $value[$attributes['type']] : $value['user_name']; + } + else + { + $value = 'not found'; + } + }*/ + $row_id = $id; + // Dirty, but the only way for now + $id = 0; + $ttl = LAN_ANONYMOUS; + + //Defaults to user_id and user_name (when present) and when idField and nameField are not present. + + + // previously set - real parameters are idField && nameField + $id = vartrue($parms['__idval']); + if($value && !is_numeric($value)) + { + $id = vartrue($parms['__idval']); + $ttl = $value; + } + elseif($value && is_numeric($value)) + { + $id = $value; + + if (vartrue($parms['__nameval'])) + { + $ttl = $parms['__nameval']; + } + else + { + $user = e107::user($value); + if (vartrue($user['user_name'])) + { + $ttl = $user['user_name']; + } + } + } + + + if(!empty($parms['link']) && $id && $ttl && is_numeric($id)) + { + // Stay in admin area. + $link = e_ADMIN."users.php?mode=main&action=edit&id=".$id."&readonly=1&iframe=1"; // e107::getUrl()->create('user/profile/view', array('id' => $id, 'name' => $ttl)) + + $value = ''.$ttl.''; + } + else + { + $value = $ttl; + } + + // Inline Editing. + if(!vartrue($attributes['noedit']) && vartrue($parms['editable']) && !vartrue($parms['link'])) // avoid bad markup, better solution coming up + { + // Need a Unique Field ID to store field settings using e107::js('settings'). + $fieldID = $this->name2id($field . '_' . microtime(true)); + // Unique ID for each rows. + $eEditableID = $this->name2id($fieldID . '_' . $row_id); + // $tpl = $this->userpicker($field, '', $ttl, $id, array('id' => $fieldID, 'selectize' => array('e_editable' => $eEditableID))); + + $tpl = $this->userpicker($fieldID, array('user_id'=>$id, 'user_name'=>$ttl), array('id' => $fieldID, 'inline' => $eEditableID)); + $mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); + $value = "" . $ttl . ""; + } + + break; + + case 'bool': + case 'boolean': + $false = vartrue($parms['trueonly']) ? "" : ADMIN_FALSE_ICON; + + if(!vartrue($attributes['noedit']) && vartrue($parms['editable']) && !vartrue($parms['link'])) // avoid bad markup, better solution coming up + { + if(isset($parms['false'])) // custom representation for 'false'. (supports font-awesome when set by css) + { + $false = $parms['false']; + } + else + { + $false = ($value === '') ? "□" : "✗"; + } + + $true = varset($parms['true'],'✓'); // custom representation for 'true'. (supports font-awesome when set by css) + + // $true = '\f00c'; + // $false = '\f00d'; + + $value = intval($value); + + $wparms = (vartrue($parms['reverse'])) ? array(0=>$true, 1=>$false) : array(0=>$false, 1=>$true); + $dispValue = $wparms[$value]; + + return $this->renderInline($field, $id, $attributes['title'], $value, $dispValue, 'select', $wparms, array('class'=>'e-editable-boolean')); + } + + if(vartrue($parms['reverse'])) + { + $value = ($value) ? $false : ADMIN_TRUE_ICON; + } + else + { + $value = $value ? ADMIN_TRUE_ICON : $false; + } + + break; + + case 'url': + if(!$value) break; + $ttl = $value; + if(vartrue($parms['href'])) + { + return $tp->replaceConstants(vartrue($parms['pre']).$value, varset($parms['replace_mod'],'abs')); + } + if(vartrue($parms['truncate'])) + { + $ttl = $tp->text_truncate($value, $parms['truncate'], '...'); + } + $value = "".$ttl.""; + break; + + case 'email': + if(!$value) break; + $ttl = $value; + if(vartrue($parms['truncate'])) + { + $ttl = $tp->text_truncate($value, $parms['truncate'], '...'); + } + $value = "".$ttl.""; + break; + + case 'method': // Custom Function + $method = $attributes['field']; // prevents table alias in method names. ie. u.my_method. + $_value = $value; + + if(!empty($attributes['data']) && $attributes['data'] == 'array') // FIXME @SecretR - please move this to where it should be. + { + $value = e107::unserialize($value); // (saved as array, return it as an array) + } + + $meth = (!empty($attributes['method'])) ? $attributes['method'] : $method; + + if(strpos($meth,'::')!==false) + { + list($className,$meth) = explode('::', $meth); + $cls = new $className(); + } + else + { + $cls = $this; + } + + if(method_exists($cls,$meth)) + { + $parms['field'] = $field; + $mode = (!empty($attributes['mode'])) ? $attributes['mode'] :'read'; + $value = call_user_func_array(array($cls, $meth), array($value, $mode, $parms)); + } + else + { + $className = get_class($cls); + e107::getDebug()->log("Missing Method: ".$className."::".$meth." ".print_a($attributes,true)); + return "Missing Method"; + } + // print_a($attributes); + // Inline Editing. + if(empty($attributes['noedit']) && !empty($parms['editable'])) // avoid bad markup, better solution coming up + { + + $mode = preg_replace('/[^\w]/', '', vartrue($_GET['mode'], '')); + $methodParms = call_user_func_array(array($this, $meth), array($_value, 'inline', $parms)); + + $inlineParms = (!empty($methodParms['inlineParms'])) ? $methodParms['inlineParms'] : null; + + if(!empty($methodParms['inlineType'])) + { + $attributes['inline'] = $methodParms['inlineType']; + $methodParms = (!empty($methodParms['inlineData'])) ? $methodParms['inlineData'] : null; + } + + + + if(is_string($attributes['inline'])) // text, textarea, select, checklist. + { + switch ($attributes['inline']) + { + + case 'checklist': + $xtype = 'checklist'; + break; + + case 'select': + case 'dropdown': + $xtype = 'select'; + break; + + case 'textarea': + $xtype = 'textarea'; + break; + + + default: + $xtype = 'text'; + $methodParms = null; + break; + } + } + + if(!empty($xtype)) + { + $value = varset($inlineParms['pre'],'').$this->renderInline($field, $id, $attributes['title'], $_value, $value, $xtype, $methodParms,$inlineParms).varset($inlineParms['post'],''); + } + + } + + break; + + case 'hidden': + return (vartrue($parms['show']) ? ($value ? $value : vartrue($parms['empty'])) : ''); + break; + + case 'language': // All Known Languages. + + if(!empty($value)) + { + $_value = $value; + if(strlen($value) === 2) + { + $value = e107::getLanguage()->convert($value); + } + } + + if(!vartrue($attributes['noedit']) && vartrue($parms['editable'])) + { + $wparms = e107::getLanguage()->getList(); + return $this->renderInline($field, $id, $attributes['title'], $_value, $value, 'select', $wparms); + } + + return $value; + + break; + + case 'lanlist': // installed languages. + $options = e107::getLanguage()->getLanSelectArray(); + + if($options) // FIXME - add support for multi-level arrays (option groups) + { + if(!is_array($attributes['writeParms'])) parse_str($attributes['writeParms'], $attributes['writeParms']); + $wparms = $attributes['writeParms']; + if(!is_array(varset($wparms['__options']))) parse_str($wparms['__options'], $wparms['__options']); + $opts = $wparms['__options']; + if($opts['multiple']) + { + $ret = array(); + $value = is_array($value) ? $value : explode(',', $value); + foreach ($value as $v) + { + if(isset($options[$v])) $ret[] = $options[$v]; + } + $value = implode(', ', $ret); + } + else + { + $ret = ''; + if(isset($options[$value])) $ret = $options[$value]; + $value = $ret; + } + $value = ($value ? vartrue($parms['pre']).$value.vartrue($parms['post']) : ''); + } + else + { + $value = ''; + } + break; + + //TODO - order + + default: + $value = $this->renderLink($value,$parms,$id); + //unknown type + break; + } + + return $value; + } + + /** + * Auto-render Form Element + * @param string $key + * @param mixed $value + * @param array $attributes field attributes including render parameters, element options - see e_admin_ui::$fields for required format + * #param array (under construction) $required_data required array as defined in e_model/validator + * @param mixed $attributes['writeParms']['default'] default value when empty (or default option when type='dropdown') + * @param mixed $attributes['writeParms']['defaultValue'] default option value when type='dropdown' + * @param mixed $attributes['writeParms']['empty'] default value when value is empty (dropdown and hidden only right now) + * @return string + */ + function renderElement($key, $value, $attributes, $required_data = array(), $id = 0) + { + $tp = e107::getParser(); + + $parms = vartrue($attributes['writeParms'], array()); + + if($tmpOpt = $tp->isJSON($parms)) + { + $parms = $tmpOpt; + unset($tmpOpt); + } + + if(is_string($parms)) parse_str($parms, $parms); + + $ajaxParms = array(); + + if(!empty($parms['ajax'])) + { + $ajaxParms['data-src'] = varset($parms['ajax']['src']); + $ajaxParms['data-target'] = varset($parms['ajax']['target']); + $ajaxParms['data-method'] = varset($parms['ajax']['method'], 'html'); + $ajaxParms['data-loading'] = varset($parms['ajax']['loading'], 'fa-spinner'); //$tp->toGlyph('fa-spinner', array('spin'=>1)) + + unset($attributes['writeParms']['ajax']); + + // e107::getDebug()->log($parms['ajax']); + } + + if(!empty($attributes['multilan'])) + { + $value = is_array($value) ? varset($value[e_LANGUAGE],'') : $value; + $parms['post'] = "".$tp->toGlyph('fa-language')."".varset($parms['post']); + $key = $key.'['.e_LANGUAGE.']'; + } + + if(empty($value) && !empty($parms['default']) && $attributes['type'] !== 'dropdown') // Allow writeParms to set default value. + { + $value = $parms['default']; + } + + // Two modes of read-only. 1 = read-only, but only when there is a value, 2 = read-only regardless. + if(vartrue($attributes['readonly']) && (vartrue($value) || vartrue($attributes['readonly'])===2)) // quick fix (maybe 'noedit'=>'readonly'?) + { + if(vartrue($attributes['writeParms'])) // eg. different size thumbnail on the edit page. + { + $attributes['readParms'] = $attributes['writeParms']; + } + return $this->renderValue($key, $value, $attributes).$this->hidden($key, $value); // + } + + // FIXME standard - writeParams['__options'] is introduced for list elements, bundle adding to writeParms is non reliable way + $writeParamsOptionable = array('dropdown', 'comma', 'radio', 'lanlist', 'language', 'user'); + $writeParamsDisabled = array('layouts', 'templates', 'userclass', 'userclasses'); + + // FIXME it breaks all list like elements - dropdowns, radio, etc + if(vartrue($required_data[0]) || vartrue($attributes['required'])) // HTML5 'required' attribute + { + // FIXME - another approach, raise standards, remove checks + if(in_array($attributes['type'], $writeParamsOptionable)) + { + $parms['__options']['required'] = 1; + } + elseif(!in_array($attributes['type'], $writeParamsDisabled)) + { + $parms['required'] = 1; + } + } + + // FIXME it breaks all list like elements - dropdowns, radio, etc + if(vartrue($required_data[3]) || vartrue($attributes['pattern'])) // HTML5 'pattern' attribute + { + // FIXME - another approach, raise standards, remove checks + if(in_array($attributes['type'], $writeParamsOptionable)) + { + $parms['__options']['pattern'] = vartrue($attributes['pattern'], $required_data[3]); + } + elseif(!in_array($attributes['type'], $writeParamsDisabled)) + { + $parms['pattern'] = vartrue($attributes['pattern'], $required_data[3]); + } + } + + + + // XXX Fixes For the above. - use optArray variable. eg. $field['key']['writeParms']['optArray'] = array('one','two','three'); + if(($attributes['type'] == 'dropdown' || $attributes['type'] == 'radio' || $attributes['type'] == 'checkboxes') && !empty($parms['optArray'])) + { + $fopts = $parms; + $parms = $fopts['optArray']; + unset($fopts['optArray']); + $parms['__options'] = $fopts; + } + + $this->renderElementTrigger($key, $value, $parms, $required_data, $id); + + switch($attributes['type']) + { + case 'number': + $maxlength = vartrue($parms['maxlength'], 255); + unset($parms['maxlength']); + if(!vartrue($parms['size'])) $parms['size'] = 'small'; + if(!vartrue($parms['class'])) $parms['class'] = 'tbox number e-spinner '; + if(!$value) $value = '0'; + $ret = vartrue($parms['pre']).$this->number($key, $value, $maxlength, $parms).vartrue($parms['post']); + break; + + case 'country': + $ret = vartrue($parms['pre']).$this->country($key, $value, $parms).vartrue($parms['post']); + break; + + case 'ip': + $ret = vartrue($parms['pre']).$this->text($key, e107::getIPHandler()->ipDecode($value), 32, $parms).vartrue($parms['post']); + break; + + case 'email': + $maxlength = vartrue($parms['maxlength'], 255); + unset($parms['maxlength']); + $ret = vartrue($parms['pre']).$this->email($key, $value, $maxlength, $parms).vartrue($parms['post']); // vartrue($parms['__options']) is limited. See 'required'=>true + break; + + case 'url': + $maxlength = vartrue($parms['maxlength'], 255); + unset($parms['maxlength']); + $ret = vartrue($parms['pre']).$this->url($key, $value, $maxlength, $parms).vartrue($parms['post']); // vartrue($parms['__options']) is limited. See 'required'=>true + + break; + // case 'email': + + case 'password': // encrypts to md5 when saved. + $maxlength = vartrue($parms['maxlength'], 255); + unset($parms['maxlength']); + if(!isset($parms['required'])) + { + + $parms['required'] = false; + } + $ret = vartrue($parms['pre']).$this->password($key, $value, $maxlength, $parms).vartrue($parms['post']); // vartrue($parms['__options']) is limited. See 'required'=>true + + break; + + case 'text': + case 'progressbar': + + $maxlength = vartrue($parms['maxlength'], 255); + unset($parms['maxlength']); + + if(!empty($parms['sef']) && e_LANGUAGE != "Japanese" && e_LANGUAGE != "Korean" && e_LANGUAGE != "Hebrew") // unsupported languages.(FIXME there are more) + { + $sefSource = $this->name2id($parms['sef']); + $sefTarget = $this->name2id($key); + if(!empty($parms['tdClassRight'])) + { + $parms['tdClassRight'] .= 'input-group'; + } + else + { + $parms['tdClassRight'] = 'input-group'; + } + + $parms['post'] = "".LAN_GENERATE.""; + } + + if(!empty($parms['password'])) // password mechanism without the md5 storage. + { + $ret = vartrue($parms['pre']).$this->password($key, $value, $maxlength, $parms).vartrue($parms['post']); + } + + else + { + $ret = vartrue($parms['pre']).$this->text($key, $value, $maxlength, $parms).vartrue($parms['post']); // vartrue($parms['__options']) is limited. See 'required'=>true + } + + + if(!empty($attributes['multilan'])) + { + $msize = vartrue($parms['size'], 'xxlarge'); + $ret = "".$ret.""; + } + + break; + + case 'tags': + $maxlength = vartrue($parms['maxlength'], 255); + $ret = vartrue($parms['pre']).$this->tags($key, $value, $maxlength, $parms).vartrue($parms['post']); // vartrue($parms['__options']) is limited. See 'required'=>true + break; + + case 'textarea': + $text = ""; + if(vartrue($parms['append']) && vartrue($value)) // similar to comments - TODO TBD. a 'comment' field type may be better. + { + $attributes['readParms'] = 'bb=1'; + + $text = $this->renderValue($key, $value, $attributes); + $text .= '
'; + $value = ""; + + // Appending needs is performed and customized using function: beforeUpdate($new_data, $old_data, $id) + } + + if(empty($parms['size'])) + { + $parms['size'] = 'xxlarge'; + } + + + $text .= vartrue($parms['pre']).$this->textarea($key, $value, vartrue($parms['rows'], 5), vartrue($parms['cols'], 40), vartrue($parms['__options'],$parms), varset($parms['counter'], false)).vartrue($parms['post']); + $ret = $text; + break; + + case 'bbarea': + $options = array('counter' => varset($parms['counter'], false)); + // Media = media-category owner used by media-manager. + $ret = vartrue($parms['pre']).$this->bbarea($key, $value, vartrue($parms['template']), vartrue($parms['media'],'_common_image'), vartrue($parms['size'], 'medium'),$options ).vartrue($parms['post']); + break; + + case 'video': + case 'image': //TODO - thumb, image list shortcode, js tooltip... + $label = varset($parms['label'], 'LAN_EDIT'); + + if(!empty($parms['optArray'])) + { + + return $this->imageradio($key,$value,$parms); + } + + + unset($parms['label']); + + if($attributes['type'] === 'video') + { + $parms['video'] = 2; // ie. video only. + $parms['w'] = 280; + } + + + $ret = $this->imagepicker($key, $value, defset($label, $label), $parms); + break; + + case 'images': + // return print_a($value, true); + $ret = ""; + $label = varset($parms['label'], 'LAN_EDIT'); + $max = varset($parms['max'],5); + + $ret .= "
"; + + for ($i=0; $i < $max; $i++) + { + $k = $key.'['.$i.'][path]'; + $ival = $value[$i]['path']; + + $ret .= $this->imagepicker($k, $ival, defset($label, $label), $parms); + } + + $ret .= "
"; + break; + + /** Generic Media Pick for combinations of images, audio, video, glyphs, files, etc. Field Type = json */ + case 'media': + + $max = varset($parms['max'],1); + + $ret = "
"; + for ($i=0; $i < $max; $i++) + { + $k = $key.'['.$i.'][path]'; + $ival = $value[$i]['path']; + + $ret .= $this->mediapicker($k, $ival, $parms); + } + + $ret .= "
"; + + return $ret; + break; + + case 'files': + + if($attributes['data'] == 'array') + { + $parms['data'] = 'array'; + } + + $ret = '
    '; + for ($i=0; $i < 5; $i++) + { + // $k = $key.'['.$i.'][path]'; + // $ival = $value[$i]['path']; + $k = $key.'['.$i.']'; + $ival = $value[$i]; + $ret .= '
  1. '.$this->filepicker($k, $ival, defset($label, $label), $parms).'
  2. '; + } + $ret .= '
'; + break; + + case 'file': //TODO - thumb, image list shortcode, js tooltip... + $label = varset($parms['label'], 'LAN_EDIT'); + unset($parms['label']); + $ret = $this->filepicker($key, $value, defset($label, $label), $parms); + break; + + case 'icon': + $label = varset($parms['label'], 'LAN_EDIT'); + $ajax = varset($parms['ajax'], true) ? true : false; + unset($parms['label'], $parms['ajax']); + $ret = $this->iconpicker($key, $value, defset($label, $label), $parms, $ajax); + break; + + case 'date': // date will show the datepicker but won't convert the value to unix. ie. string value will be saved. (or may be processed manually with beforeCreate() etc. Format may be determined by $parm. + case 'datestamp': + // If hidden, value is updated regardless. eg. a 'last updated' field. + // If not hidden, and there is a value, it is retained. eg. during the update of an existing record. + // otherwise it is added. eg. during the creation of a new record. + if(vartrue($parms['auto']) && (($value == null) || vartrue($parms['hidden']))) + { + $value = time(); + } + + if(vartrue($parms['readonly'])) // different to 'attribute-readonly' since the value may be auto-generated. + { + $ret = $this->renderValue($key, $value, $attributes).$this->hidden($key, $value); + } + elseif(vartrue($parms['hidden'])) + { + $ret = $this->hidden($key, $value); + } + else + { + $ret = $this->datepicker($key, $value, $parms); + } + break; + + case 'layouts': //to do - exclude param (exact match) + + $location = varset($parms['plugin']); // empty - core + $ilocation = vartrue($parms['id'], $location); // omit if same as plugin name + $where = vartrue($parms['area'], 'front'); //default is 'front' + $filter = varset($parms['filter']); + $merge = isset($parms['merge']) ? (bool) $parms['merge'] : true; + + $layouts = e107::getLayouts($location, $ilocation, $where, $filter, $merge, false); + + return vartrue($parms['pre'],'').$this->select($key, $layouts,$value,$parms).vartrue($parms['post'],''); + + /* if($tmp = e107::getTemplateInfo($location,$ilocation, null,true,$merge)) // read xxxx_INFO array from template file. + { + $opt = array(); + foreach($tmp as $k=>$inf) + { + $opt[$k] = $inf['title']; + } + + return vartrue($parms['pre'],'').$this->select($key,$opt,$value,$parms).vartrue($parms['post'],''); + }*/ + + + +/* + if(varset($parms['default']) && !isset($layouts[0]['default'])) + { + $layouts[0] = array('default' => $parms['default']) + $layouts[0]; + } + $info = array(); + if($layouts[1]) + { + foreach ($layouts[1] as $k => $info_array) + { + if(isset($info_array['description'])) + $info[$k] = defset($info_array['description'], $info_array['description']); + } + } + + */ + + //$this->selectbox($key, $layouts, $value) + // $ret = (vartrue($parms['raw']) ? $layouts[0] : $this->radio_multi($key, $layouts[0], $value,array('sep'=>"
"), $info)); + break; + + case 'templates': //to do - exclude param (exact match) + $templates = array(); + if(varset($parms['default'])) + { + $templates['default'] = defset($parms['default'], $parms['default']); + } + $location = vartrue($parms['plugin']) ? e_PLUGIN.$parms['plugin'].'/' : e_THEME; + $ilocation = vartrue($parms['location']); + $tmp = e107::getFile()->get_files($location.'templates/'.$ilocation, vartrue($parms['fmask'], '_template\.php$'), vartrue($parms['omit'], 'standard'), vartrue($parms['recurse_level'], 0)); + foreach(self::sort_get_files_output($tmp) as $files) + { + $k = str_replace('_template.php', '', $files['fname']); + $templates[$k] = implode(' ', array_map('ucfirst', explode('_', $k))); //TODO add LANS? + } + + // override + $where = vartrue($parms['area'], 'front'); + $location = vartrue($parms['plugin']) ? $parms['plugin'].'/' : ''; + $tmp = e107::getFile()->get_files(e107::getThemeInfo($where, 'rel').'templates/'.$location.$ilocation, vartrue($parms['fmask']), vartrue($parms['omit'], 'standard'), vartrue($parms['recurse_level'], 0)); + foreach(self::sort_get_files_output($tmp) as $files) + { + $k = str_replace('_template.php', '', $files['fname']); + $templates[$k] = implode(' ', array_map('ucfirst', explode('_', $k))); //TODO add LANS? + } + $ret = (vartrue($parms['raw']) ? $templates : $this->selectbox($key, $templates, $value)); + break; + + case 'checkboxes': + + if(is_array($parms)) + { + $eloptions = vartrue($parms['__options'], array()); + if(is_string($eloptions)) parse_str($eloptions, $eloptions); + if($attributes['type'] === 'comma') $eloptions['multiple'] = true; + unset($parms['__options']); + + if(!is_array($value) && !empty($value)) + { + $value = explode(",",$value); + } + + + $ret = vartrue($eloptions['pre']).$this->checkboxes($key, $parms, $value, $eloptions).vartrue($eloptions['post']); + + + } + return $ret; + break; + + + case 'dropdown': + case 'comma': + + + if(!empty($attributes['writeParms']['optArray'])) + { + $eloptions = $attributes['writeParms']; + unset($eloptions['optArray']); + } + else + { + $eloptions = vartrue($parms['__options'], array()); + } + + $value = (isset($eloptions['empty']) && ($value === null)) ? $eloptions['empty'] : $value; + + if(is_string($eloptions)) parse_str($eloptions, $eloptions); + if($attributes['type'] === 'comma') $eloptions['multiple'] = true; + unset($parms['__options']); + if(vartrue($eloptions['multiple']) && !is_array($value)) $value = explode(',', $value); + + // Allow Ajax API. + if(!empty($ajaxParms)) + { + $eloptions = array_merge_recursive($eloptions, $ajaxParms); + $eloptions['class'] = 'e-ajax ' . varset($eloptions['class']); + } + + $ret = vartrue($eloptions['pre']).$this->select($key, $parms, $value, $eloptions).vartrue($eloptions['post']); + break; + + case 'radio': + // TODO - more options (multi-line, help) + $eloptions = vartrue($parms['__options'], array()); + if(is_string($eloptions)) parse_str($eloptions, $eloptions); + unset($parms['__options']); + $ret = vartrue($eloptions['pre']).$this->radio_multi($key, $parms, $value, $eloptions, false).vartrue($eloptions['post']); + break; + + case 'userclass': + case 'userclasses': + + + $uc_options = vartrue($parms['classlist'], 'public,guest,nobody,member,admin,main,classes'); // defaults to 'public,guest,nobody,member,classes' (userclass handler) + unset($parms['classlist']); + + + // $method = ($attributes['type'] == 'userclass') ? 'uc_select' : 'uc_select'; + if(vartrue($attributes['type']) == 'userclasses'){ $parms['multiple'] = true; } + + $ret = vartrue($parms['pre']).$this->uc_select($key, $value, $uc_options, vartrue($parms, array())). vartrue($parms['post']); + break; + + /*case 'user_name': + case 'user_loginname': + case 'user_login': + case 'user_customtitle': + case 'user_email':*/ + case 'user': + //user_id expected + // Just temporary solution, could be changed soon + + + if(!isset($parms['__options'])) $parms['__options'] = array(); + if(!is_array($parms['__options'])) parse_str($parms['__options'], $parms['__options']); + + if((empty($value) || !empty($parms['currentInit']) && empty($parms['default']) ) || !empty($parms['current']) || (vartrue($parms['default']) == 'USERID')) // include current user by default. + { + $value = array('user_id'=>USERID, 'user_name'=>USERNAME); + if(vartrue($parms['current'])) + { + $parms['__options']['readonly'] = true; + } + + } + + + + + + // if(!is_array($value)) + // { + // $value = $value ? e107::getSystemUser($value, true)->getUserData() : array();// e107::user($value); + // } + + $colname = vartrue($parms['nameType'], 'user_name'); + $parms['__options']['name'] = $colname; + + // if(!$value) $value = array(); + // $uname = varset($value[$colname]); + // $value = varset($value['user_id'], 0); + + if(!empty($parms['limit'])) + { + $parms['__options']['limit'] = intval($parms['limit']); + } + + $ret = $this->userpicker(vartrue($parms['nameField'], $key), $value, vartrue($parms['__options'])); + + // $ret = $this->userpicker(vartrue($parms['nameField'], $key), $key, $uname, $value, vartrue($parms['__options'])); + break; + + + + + case 'bool': + case 'boolean': + + if(varset($parms['label']) === 'yesno') + { + $lenabled = 'LAN_YES'; + $ldisabled = 'LAN_NO'; + } + else + { + $lenabled = vartrue($parms['enabled'], 'LAN_ON'); + $ldisabled = (!empty($parms['disabled']) && is_string($parms['disabled'])) ? $parms['disabled'] : 'LAN_OFF'; + } + + unset($parms['enabled'], $parms['disabled'], $parms['label']); + $ret = vartrue($parms['pre']).$this->radio_switch($key, $value, defset($lenabled, $lenabled), defset($ldisabled, $ldisabled),$parms).vartrue($parms['post']); + break; + + case "checkbox": + + $value = (isset($parms['value'])) ? $parms['value'] : $value; + $ret = vartrue($parms['pre']).$this->checkbox($key, 1, $value,$parms).vartrue($parms['post']); + break; + + case 'method': // Custom Function + $meth = (!empty($attributes['method'])) ? $attributes['method'] : $key; + $parms['field'] = $key; + + if(strpos($meth,'::')!==false) + { + list($className,$meth) = explode('::', $meth); + $cls = new $className; + } + else + { + $cls = $this; + } + + $ret = call_user_func_array(array($cls, $meth), array($value, 'write', $parms)); + break; + + case 'upload': //TODO - from method + // TODO uploadfile SC is now processing uploads as well (add it to admin UI), write/readParms have to be added (see uploadfile.php parms) + $disbut = varset($parms['disable_button'], '0'); + $ret = $tp->parseTemplate("{UPLOADFILE=".(vartrue($parms['path']) ? e107::getParser()->replaceConstants($parms['path']) : e_UPLOAD)."|nowarn&trigger=etrigger_uploadfiles&disable_button={$disbut}}"); + break; + + case 'hidden': + + $value = (isset($parms['value'])) ? $parms['value'] : $value; + $ret = (vartrue($parms['show']) ? ($value ? $value : varset($parms['empty'], $value)) : ''); + $ret = $ret.$this->hidden($key, $value); + break; + + case 'lanlist': // installed languages + case 'language': // all languages + + $options = ($attributes['type'] === 'language') ? e107::getLanguage()->getList() : e107::getLanguage()->getLanSelectArray(); + + $eloptions = vartrue($parms['__options'], array()); + if(!is_array($eloptions)) parse_str($eloptions, $eloptions); + unset($parms['__options']); + if(vartrue($eloptions['multiple']) && !is_array($value)) $value = explode(',', $value); + $ret = vartrue($eloptions['pre']).$this->selectbox($key, $options, $value, $eloptions).vartrue($eloptions['post']); + break; + + case null: + // Possibly used in db but should not be submitted in form. @see news_extended. + break; + + default:// No LAN necessary, debug only. + $ret = (ADMIN) ? "".LAN_ERROR." Unknown 'type' : ".$attributes['type'] ."" : $value; + break; + } + + if(vartrue($parms['expand'])) + { + $k = "exp-".$this->name2id($key); + $text = "".$parms['expand'].""; + $text .= vartrue($parms['help']) ? '
'.$parms['help'].'
' : ''; + $text .= "
".$ret."
"; + return $text; + } + else + { + /** @deprecated usage @see renderCreateFieldset() should be attributes['help'] */ + $ret .= vartrue($parms['help']) ? '
'.$tp->toHTML($parms['help'],false,'defs').'
' : ''; + } + + return $ret; + } + + + private function imageradio($name,$value,$parms) + { + + if(!empty($parms['path'])) + { + $parms['legacy'] = $parms['path']; + } + + + $text = '
'; + + + + foreach($parms['optArray'] as $key=>$val) + { + $thumbnail = e107::getParser()->toImage($val,$parms); + + // $thumbnail = "".$val.""; + + + $selected = ($val == $value) ? " checked" : ""; + + $text .= " +
+ +
"; + + } + + $text .= "
"; + + return $text; + + } + + + + /** + * Generic List Form, used internally by admin UI + * Expected options array format: + * + * 'myplugin', // unique string used for building element ids, REQUIRED + * 'pid' => 'primary_id', // primary field name, REQUIRED + * 'url' => '{e_PLUGIN}myplug/admin_config.php', // if not set, e_SELF is used + * 'query' => 'mode=main&action=list', // or e_QUERY if not set + * 'head_query' => 'mode=main&action=list', // without field, asc and from vars, REQUIRED + * 'np_query' => 'mode=main&action=list', // without from var, REQUIRED for next/prev functionality + * 'legend' => 'Fieldset Legend', // hidden by default + * 'form_pre' => '', // markup to be added before opening form element (e.g. Filter form) + * 'form_post' => '', // markup to be added after closing form element + * 'fields' => array(...), // see e_admin_ui::$fields + * 'fieldpref' => array(...), // see e_admin_ui::$fieldpref + * 'table_pre' => '', // markup to be added before opening table element + * 'table_post' => '', // markup to be added after closing table element (e.g. Batch actions) + * 'fieldset_pre' => '', // markup to be added before opening fieldset element + * 'fieldset_post' => '', // markup to be added after closing fieldset element + * 'perPage' => 15, // if 0 - no next/prev navigation + * 'from' => 0, // current page, default 0 + * 'field' => 'field_name', //current order field name, default - primary field + * 'asc' => 'desc', //current 'order by' rule, default 'asc' + * ); + * $tree_models['myplugin'] = new e_admin_tree_model($data); + * + * TODO - move fieldset & table generation in separate methods, needed for ajax calls + * @param array $form_options + * @param e_admin_tree_model $tree_model + * @param boolean $nocontainer don't enclose form in div container + * @return string + */ + public function renderListForm($form_options, $tree_models, $nocontainer = false) + { + $tp = e107::getParser(); + $text = ''; + + + // print_a($form_options); + + foreach ($form_options as $fid => $options) + { + /** @var e_tree_model $tree_model */ + $tree_model = $tree_models[$fid]; + $tree = $tree_model->getTree(); + $total = $tree_model->getTotal(); + + $amount = $options['perPage']; + $from = vartrue($options['from'], 0); + $field = vartrue($options['field'], $options['pid']); + $asc = strtoupper(vartrue($options['asc'], 'asc')); + $elid = $fid;//$options['id']; + $query = vartrue($options['query'],e_QUERY); // ? $options['query'] : ; + if(vartrue($_GET['action']) == 'list') + { + $query = e_QUERY; //XXX Quick fix for loss of pagination after 'delete'. + } + $url = (isset($options['url']) ? $tp->replaceConstants($options['url'], 'abs') : e_SELF); + $formurl = $url.($query ? '?'.$query : ''); + $fields = $options['fields']; + $current_fields = varset($options['fieldpref']) ? $options['fieldpref'] : array_keys($options['fields']); + $legend_class = vartrue($options['legend_class'], 'e-hideme'); + + + + $text .= " +
+
".$this->token()." + ".vartrue($options['fieldset_pre'])." +
+ ".$options['legend']." + ".vartrue($options['table_pre'])." + + ".$this->colGroup($fields, $current_fields)." + ".$this->thead($fields, $current_fields, varset($options['head_query']), varset($options['query']))." + + "; + + if(!$tree) + { + $text .= " + +
"; + + $text .= "
".LAN_NO_RECORDS_FOUND."
"; // not prone to column-count issues. + } + else + { + /** @var e_model $model */ + foreach($tree as $model) + { + // $model->set('x_canonical_url', 'whatever'); + // var_dump($model); + e107::setRegistry('core/adminUI/currentListModel', $model); + $text .= $this->renderTableRow($fields, $current_fields, $model->getData(), $options['pid']); + } + + e107::setRegistry('core/adminUI/currentListModel', null); + + $text .= " + "; + } + + + $text .= vartrue($options['table_post']); + + + if($tree && $amount) + { + // New nextprev SC parameters + $parms = 'total='.$total; + $parms .= '&amount='.$amount; + $parms .= '¤t='.$from; + if(ADMIN_AREA) + { + $parms .= '&tmpl_prefix=admin'; + } + + // NOTE - the whole url is double encoded - reason is to not break parms query string + // 'np_query' should be proper (urlencode'd) url query string + $url = rawurlencode($url.'?'.(varset($options['np_query']) ? str_replace(array('&', '&'), array('&', '&'), $options['np_query']).'&' : '').'from=[FROM]'); + $parms .= '&url='.$url; + //$parms = $total.",".$amount.",".$from.",".$url.'?'.($options['np_query'] ? $options['np_query'].'&' : '').'from=[FROM]'; + //$text .= $tp->parseTemplate("{NEXTPREV={$parms}}"); + $nextprev = $tp->parseTemplate("{NEXTPREV={$parms}}"); + if ($nextprev) + { + $text .= "
".$nextprev."
"; + } + } + + $text .= " +
+ ".vartrue($options['fieldset_post'])." +
+
+ "; + } + if(!$nocontainer) + { + $text = '
'.$text.'
'; + } + return (vartrue($options['form_pre']).$text.vartrue($options['form_post'])); + } + + + /** + * Used with 'carousel' generates slides with X number of cells/blocks per slide. + * @param $cells + * @param int $perPage + * @return array + */ + private function slides($cells, $perPage=12) + { + $tmp = ''; + $s = 0; + $slides = array(); + foreach($cells as $cell) + { + $tmp .= $cell; + + $s++; + if($s == $perPage) + { + $slides[] = array('text'=>$tmp); + $tmp = ''; + $s = 0; + } + } + + if($s != $perPage && $s != 0) + { + $slides[] = array('text'=>$tmp); + } + + return $slides; + + + } + + + /** + * Render Grid-list layout. used internally by admin UI + * @param $form_options + * @param $tree_models + * @param bool|false $nocontainer + * @return string + */ + public function renderGridForm($form_options, $tree_models, $nocontainer = false) + { + $tp = e107::getParser(); + $text = ''; + + + // print_a($form_options); + + foreach ($form_options as $fid => $options) + { + $tree_model = $tree_models[$fid]; + $tree = $tree_model->getTree(); + $total = $tree_model->getTotal(); + + $amount = $options['perPage']; + $from = vartrue($options['from'], 0); + $field = vartrue($options['field'], $options['pid']); + $asc = strtoupper(vartrue($options['asc'], 'asc')); + $elid = $fid;//$options['id']; + $query = vartrue($options['query'],e_QUERY); // ? $options['query'] : ; + if(vartrue($_GET['action']) == 'list') + { + $query = e_QUERY; //XXX Quick fix for loss of pagination after 'delete'. + } + $url = (isset($options['url']) ? $tp->replaceConstants($options['url'], 'abs') : e_SELF); + $formurl = $url.($query ? '?'.$query : ''); + $fields = $options['fields']; + $current_fields = varset($options['fieldpref']) ? $options['fieldpref'] : array_keys($options['fields']); + $legend_class = vartrue($options['legend_class'], 'e-hideme'); + + + + $text .= " +
+
".$this->token()." + ".vartrue($options['fieldset_pre']); + + $text .= " + +
+ ".$options['legend']." + ".vartrue($options['table_pre'])." +
+ "; + + + if(!$tree) + { + $text .= "
"; + $text .= "
".LAN_NO_RECORDS_FOUND."
"; // not prone to column-count issues. + } + else + { + + + if(empty($options['grid']['template'])) + { + $template = '
+
{IMAGE} +
+ {OPTIONS} +
+
+ +
'; + } + else + { + $template = $options['grid']['template']; + } + + + $cls = !empty($options['grid']['class']) ? $options['grid']['class'] : 'col-md-2'; + $pid = $options['pid']; + $perPage = $options['grid']['perPage']; + + + + $gridFields = $options['grid']; + $gridFields['options'] = 'options'; + $gridFields['checkbox'] = 'checkboxes'; + + unset($gridFields['class'],$gridFields['perPage'], $gridFields['carousel']); + + $cells = array(); + foreach($tree as $model) + { + e107::setRegistry('core/adminUI/currentListModel', $model); + + $data = $model->getData(); + + $id = $data[$pid]; + $vars = array(); + + foreach($gridFields as $k=>$v) + { + $key = strtoupper($k); + $fields[$v]['grid'] = true; + $vars[$key] = $this->renderValue($v,$data[$v],$fields[$v],$id); + } + + $cells[] = "
". $tp->simpleParse($template,$vars). "
"; + + } + + + if($options['grid']['carousel'] === true) + { + $slides = $this->slides($cells, $perPage); + $carouselData = $this->carousel('admin-ui-carousel',$slides, array('wrap'=>false, 'interval'=>false, 'data'=>true)); + + $text .= $carouselData['start'].$carouselData['inner'].$carouselData['end']; + + } + else + { + $text .= implode("\n",$cells); + } + + + e107::setRegistry('core/adminUI/currentListModel', null); + + $text .= "
+
"; + } + + + $text .= vartrue($options['table_post']); + + + if($tree && $amount) + { + // New nextprev SC parameters + $parms = 'total='.$total; + $parms .= '&amount='.$amount; + $parms .= '¤t='.$from; + + if(ADMIN_AREA) + { + $parms .= '&tmpl_prefix=admin'; + } + + // NOTE - the whole url is double encoded - reason is to not break parms query string + // 'np_query' should be proper (urlencode'd) url query string + $url = rawurlencode($url.'?'.(varset($options['np_query']) ? str_replace(array('&', '&'), array('&', '&'), $options['np_query']).'&' : '').'from=[FROM]'); + $parms .= '&url='.$url; + //$parms = $total.",".$amount.",".$from.",".$url.'?'.($options['np_query'] ? $options['np_query'].'&' : '').'from=[FROM]'; + //$text .= $tp->parseTemplate("{NEXTPREV={$parms}}"); + $nextprev = $tp->parseTemplate("{NEXTPREV={$parms}}"); + if ($nextprev) + { + $text .= "
".$nextprev."
"; + } + } + + $text .= " + + ".vartrue($options['fieldset_post'])." +
+ + "; + } + if(!$nocontainer) + { + $text = '
'.$text.'
'; + } + return (vartrue($options['form_pre']).$text.vartrue($options['form_post'])); + } + + /** + * Generic DB Record Management Form. + * TODO - lans + * TODO - move fieldset & table generation in separate methods, needed for ajax calls + * Expected arrays format: + * + * 'myplugin', + * 'url' => '{e_PLUGIN}myplug/admin_config.php', //if not set, e_SELF is used + * 'query' => 'mode=main&action=edit&id=1', //or e_QUERY if not set + * 'tabs' => true, * + * 'fieldsets' => array( + * 'general' => array( + * 'legend' => 'Fieldset Legend', + * 'fields' => array(...), //see e_admin_ui::$fields + * 'after_submit_options' => array('action' => 'Label'[,...]), // or true for default redirect options + * 'after_submit_default' => 'action_name', + * 'triggers' => 'auto', // standard create/update-cancel triggers + * //or custom trigger array in format array('sibmit' => array('Title', 'create', '1'), 'cancel') - trigger name - title, action, optional hidden value (in this case named sibmit_value) + * ), + * + * 'advanced' => array( + * 'legend' => 'Fieldset Legend', + * 'fields' => array(...), //see e_admin_ui::$fields + * 'after_submit_options' => array('__default' => 'action_name' 'action' => 'Label'[,...]), // or true for default redirect options + * 'triggers' => 'auto', // standard create/update-cancel triggers + * //or custom trigger array in format array('submit' => array('Title', 'create', '1'), 'cancel' => array('cancel', 'cancel')) - trigger name - title, action, optional hidden value (in this case named sibmit_value) + * ) + * ) + * ); + * $models[0] = new e_admin_model($data); + * $models[0]->setFieldIdName('primary_id'); // you need to do it if you don't use your own admin model extension + * + * @param array $forms numerical array + * @param array $models numerical array with values instance of e_admin_model + * @param boolean $nocontainer don't enclose in div container + * @return string + */ + function renderCreateForm($forms, $models, $nocontainer = false) + { + $text = ''; + foreach ($forms as $fid => $form) + { + $model = $models[$fid]; + + if(!is_object($model)) + { + e107::getDebug()->log("No model object found with key ".$fid); + } + + $query = isset($form['query']) ? $form['query'] : e_QUERY ; + $url = (isset($form['url']) ? e107::getParser()->replaceConstants($form['url'], 'abs') : e_SELF).($query ? '?'.$query : ''); + $curTab = strval(varset($_GET['tab'],'0')); + + $text .= " +
+
+
+ ".vartrue($form['header'])." + ".$this->token()." + "; + + foreach ($form['fieldsets'] as $elid => $data) + { + $elid = $form['id'].'-'.$elid; + + + if(vartrue($data['tabs'])) // Tabs Present + { + $text .= '
'; + + foreach($data['tabs'] as $tabId=>$label) + { + $active = (strval($tabId) === $curTab) ? 'active' : ''; + $text .= '
'; + + // e107::getDebug()->log('elid: '.$elid. " tabid: ".$tabId); + // e107::getDebug()->log($data); + // e107::getDebug()->log($model); + + + $text .= $this->renderCreateFieldset($elid, $data, $model, $tabId); + $text .= "
"; + } + + $text .= "
"; + $text .= $this->renderCreateButtonsBar($elid, $data, $model, $tabId); // Create/Update Buttons etc. + + } + else // No Tabs Present + { + $text .= $this->renderCreateFieldset($elid, $data, $model, false); + $text .= $this->renderCreateButtonsBar($elid, $data, $model, false); // Create/Update Buttons etc. + } + + + } + + $text .= " + ".vartrue($form['footer'])." +
+
+ "; + + // e107::js('footer-inline',"Form.focusFirstElement('{$form['id']}-form');",'prototype'); + // e107::getJs()->footerInline("Form.focusFirstElement('{$form['id']}-form');"); + } + if(!$nocontainer) + { + $text = '
'.$text.'
'; + } + return $text; + } + + /** + * Create form fieldset, called internal by {@link renderCreateForm()) + * + * @param string $id field id + * @param array $fdata fieldset data + * @param object $model + * @return string | false + */ + function renderCreateFieldset($id, $fdata, $model, $tab=0) + { + + + $start = vartrue($fdata['fieldset_pre'])." +
+ ".vartrue($fdata['legend'])." + ".vartrue($fdata['table_pre'])." + + + + + + + "; + + $text = ''; + + // required fields - model definition + $model_required = $model->getValidationRules(); + $required_help = false; + $hidden_fields = array(); + + foreach($fdata['fields'] as $key => $att) + { + if($tab !== false && varset($att['tab'], 0) !== $tab) + { + continue; + } + + // convert aliases - not supported in edit mod + if(vartrue($att['alias']) && !$model->hasData($key)) + { + $key = $att['field']; + } + + if($key == 'checkboxes' || $key == 'options' || ($att['type'] === null) || ($att['type'] === false)) + { + continue; + } + + $parms = vartrue($att['formparms'], array()); + if(!is_array($parms)) parse_str($parms, $parms); + $label = !empty($att['note']) ? '
'.deftrue($att['note'], $att['note']).'
' : ''; + $help = !empty($att['help']) ? '
'.deftrue($att['help'], $att['help']).'
' : ''; + + + $valPath = trim(vartrue($att['dataPath'], $key), '/'); + $keyName = $key; + if(strpos($valPath, '/')) //not TRUE, cause string doesn't start with / + { + $tmp = explode('/', $valPath); + $keyName = array_shift($tmp); + foreach ($tmp as $path) + { + $keyName .= '['.$path.']'; + } + } + + if(!empty($att['writeParms']) && !is_array($att['writeParms'])) + { + parse_str(varset($att['writeParms']), $writeParms); + } + else + { + $writeParms = varset($att['writeParms']); + } + + if(!empty($writeParms['sef'])) // group sef generate button with input element. + { + if(empty($writeParms['tdClassRight'])) + { + $writeParms['tdClassRight'] = 'input-group'; + + } + else + { + $writeParms['tdClassRight'] .= ' input-group'; + } + + } + + if('hidden' === $att['type']) + { + + if(empty($writeParms['show'])) + { + $hidden_fields[] = $this->renderElement($keyName, $model->getIfPosted($valPath), $att, varset($model_required[$key], array())); + + continue; + } + unset($tmp); + } + + // type null - system (special) fields + if(vartrue($att['type']) !== null && !vartrue($att['noedit']) && $key != $model->getFieldIdName()) + { + $required = ''; + $required_class = ''; + if(isset($model_required[$key]) || vartrue($att['validate']) || !empty($att['writeParms']['required'])) + { + + $required = $this->getRequiredString(); + $required_class = ' class="required-label" title="'.LAN_REQUIRED.'"'; + $required_help = true; + + if(!empty($att['validate'])) + { + // override + $model_required[$key] = array(); + $model_required[$key][] = true === $att['validate'] ? 'required' : $att['validate']; + $model_required[$key][] = varset($att['rule']); + $model_required[$key][] = $att['title']; + $model_required[$key][] = varset($att['error']); + } + } + + /* + if('hidden' === $att['type']) + { + parse_str(varset($att['writeParms']), $tmp); + if(!vartrue($tmp['show'])) + { + $hidden_fields[] = $this->renderElement($keyName, $model->getIfPosted($valPath), $att, varset($model_required[$key], array())); + unset($tmp); + continue; + } + unset($tmp); + } + */ + + if(in_array($key,$this->_field_warnings)) + { + if(is_string($writeParms)) + { + parse_str($writeParms,$writeParms); + } + + $writeParms['tdClassRight'] .= ' has-warning'; + + } + + $leftCell = "".defset(vartrue($att['title']), vartrue($att['title']))."".$required.$label; + $rightCell = $this->renderElement($keyName, $model->getIfPosted($valPath), $att, varset($model_required[$key], array()), $model->getId())." ".$help; + + if(vartrue($att['type']) == 'bbarea' || !empty($writeParms['nolabel'])) + { + $text .= " + + + + "; + + } + else + { +// rightCellClass + // leftCellClass + $leftCellClass = (!empty($writeParms['tdClassLeft'])) ? " class='".$writeParms['tdClassLeft']."'" : ""; + $rightCellClass = (!empty($writeParms['tdClassRight'])) ? " class='".$writeParms['tdClassRight']."'" : ""; + $trClass = (!empty($writeParms['trClass'])) ? " class='".$writeParms['trClass']."'" : ""; + + $text .= " + + + ".$leftCell." + + + ".$rightCell." + + + "; + } + + + + + + } + //if($bckp) $model->remove($bckp); + + } + + //print_a($fdata); + + if($required_help) + { + $required_help = '
'.$this->getRequiredString().' - required fields
'; //TODO - lans + } + + + if(!empty($text) || !empty($hidden_fields)) + { + $text = $start.$text; + + $text .= " +
+
"; + + $text .= (isset($writeParms['nolabel']) && $writeParms['nolabel'] == 2) ? '' : "
".$leftCell."
" ; + $text .= $rightCell." +
"; + + $text .= implode("\n", $hidden_fields); + + $text .= "
"; + + $text .= vartrue($fdata['fieldset_post']); + + return $text; + } + + + + return false; + + /* + $text .= " + ".implode("\n", $hidden_fields)." + ".$required_help." + ".vartrue($fdata['table_post'])." +
+ "; + // After submit options + $defsubmitopt = array('list' => 'go to list', 'create' => 'create another', 'edit' => 'edit current'); + $submitopt = isset($fdata['after_submit_options']) ? $fdata['after_submit_options'] : true; + if(true === $submitopt) + { + $submitopt = $defsubmitopt; + } + + if($submitopt) + { + $selected = isset($fdata['after_submit_default']) && array_key_exists($fdata['after_submit_default'], $submitopt) ? $fdata['after_submit_default'] : ''; + + } + + $triggers = vartrue($fdata['triggers'], 'auto'); + if(is_string($triggers) && 'auto' === $triggers) + { + $triggers = array(); + if($model->getId()) + { + $triggers['submit'] = array(LAN_UPDATE, 'update', $model->getId()); + } + else + { + $triggers['submit'] = array(LAN_CREATE, 'create', 0); + } + $triggers['cancel'] = array(LAN_CANCEL, 'cancel'); + } + + foreach ($triggers as $trigger => $tdata) + { + $text .= ($trigger == 'submit') ? "
" : ""; + $text .= $this->admin_button('etrigger_'.$trigger, $tdata[0], $tdata[1]); + + if($trigger == 'submit' && $submitopt) + { + + $text .= + ' + '; + } + + $text .= ($trigger == 'submit') ?"
" : ""; + + if(isset($tdata[2])) + { + $text .= $this->hidden($trigger.'_value', $tdata[2]); + } + } + + $text .= " +
+ + ".vartrue($fdata['fieldset_post'])." + "; + return $text; + */ + } + + + function renderCreateButtonsBar($id, $fdata, $model, $tab=0) + { + /* + $text = vartrue($fdata['fieldset_pre'])." +
+ ".vartrue($fdata['legend'])." + ".vartrue($fdata['table_pre'])." + + + + + + + "; + */ + $text = ''; + + // required fields - model definition + $model_required = $model->getValidationRules(); + $required_help = false; + $hidden_fields = array(); + foreach($fdata['fields'] as $key => $att) + { + + if($tab !== false && varset($att['tab'], 0) !== $tab) + { + continue; + } + + // convert aliases - not supported in edit mod + if(vartrue($att['alias']) && !$model->hasData($key)) + { + $key = $att['field']; + } + + if($key == 'checkboxes' || $key == 'options') + { + continue; + } + + $parms = vartrue($att['formparms'], array()); + if(!is_array($parms)) parse_str($parms, $parms); + $label = vartrue($att['note']) ? '
'.deftrue($att['note'], $att['note']).'
' : ''; + $help = vartrue($att['help']) ? '
'.deftrue($att['help'], $att['help']).'
' : ''; + + $valPath = trim(vartrue($att['dataPath'], $key), '/'); + $keyName = $key; + if(strpos($valPath, '/')) //not TRUE, cause string doesn't start with / + { + $tmp = explode('/', $valPath); + $keyName = array_shift($tmp); + foreach ($tmp as $path) + { + $keyName .= '['.$path.']'; + } + } + + if('hidden' === $att['type']) + { + if(!is_array($att['writeParms'])) parse_str(varset($att['writeParms']), $tmp); + else $tmp = $att['writeParms']; + + if(!vartrue($tmp['show'])) + { + $hidden_fields[] = $this->renderElement($keyName, $model->getIfPosted($valPath), $att, varset($model_required[$key], array()), $model->getId()); + unset($tmp); + continue; + } + unset($tmp); + } + + // type null - system (special) fields + if(vartrue($att['type']) !== null && !vartrue($att['noedit']) && $key != $model->getFieldIdName()) + { + $required = ''; + $required_class = ''; + if(isset($model_required[$key]) || vartrue($att['validate'])) + { + $required = $this->getRequiredString(); + $required_class = ' class="required-label"'; // TODO - add 'required-label' to the core CSS definitions + $required_help = true; + if(vartrue($att['validate'])) + { + // override + $model_required[$key] = array(); + $model_required[$key][] = true === $att['validate'] ? 'required' : $att['validate']; + $model_required[$key][] = varset($att['rule']); + $model_required[$key][] = $att['title']; + $model_required[$key][] = varset($att['error']); + } + } + + /* + $text .= " + + + + + "; + * */ + } + //if($bckp) $model->remove($bckp); + + } + + if($required_help) + { + // $required_help = '
'.$this->getRequiredString().' - required fields
'; //TODO - lans + } + + // $text .= " + // + //
+ ".$required."".defset(vartrue($att['title']), vartrue($att['title']))."".$label." + + ".$this->renderElement($keyName, $model->getIfPosted($valPath), $att, varset($model_required[$key], array()))." + {$help} +
"; + + + + $text .= " + ".implode("\n", $hidden_fields)." + ".vartrue($fdata['table_post'])." +
+ "; + // After submit options + $defsubmitopt = array('list' => LAN_EFORM_013, 'create' => LAN_EFORM_014, 'edit' => LAN_EFORM_015); + $submitopt = isset($fdata['after_submit_options']) ? $fdata['after_submit_options'] : true; + + if(true === $submitopt) + { + $submitopt = $defsubmitopt; + } + + if($submitopt) + { + $selected = isset($fdata['after_submit_default']) && array_key_exists($fdata['after_submit_default'], $submitopt) ? $fdata['after_submit_default'] : 'list'; + } + + $triggers = (empty($fdata['triggers']) && $fdata['triggers'] !== false) ? 'auto' : $fdata['triggers']; // vartrue($fdata['triggers'], 'auto'); + if(is_string($triggers) && 'auto' === $triggers) + { + $triggers = array(); + if($model->getId()) + { + $triggers['submit'] = array(LAN_UPDATE, 'update', $model->getId()); + } + else + { + $triggers['submit'] = array(LAN_CREATE, 'create', 0); + } + $triggers['cancel'] = array(LAN_CANCEL, 'cancel'); + } + + if(!empty($triggers)) + { + foreach ($triggers as $trigger => $tdata) + { + $text .= ($trigger == 'submit') ? "
" : ""; + $text .= $this->admin_button('etrigger_'.$trigger, $tdata[1], $tdata[1], $tdata[0]); + + if($trigger == 'submit' && $submitopt) + { + + $text .= + ' + '; + } + + $text .= ($trigger == 'submit') ?"
" : ""; + + if(isset($tdata[2])) + { + $text .= $this->hidden($trigger.'_value', $tdata[2]); + } + } + } + + $text .= " +
+ + ".vartrue($fdata['fieldset_post'])." + "; + return $text; + } + + + /** + * Generic renderForm solution + * @param @forms + * @param @nocontainer + * @return string + */ + function renderForm($forms, $nocontainer = false) + { + $text = ''; + foreach ($forms as $fid => $form) + { + $query = isset($form['query']) ? $form['query'] : e_QUERY ; + $url = (isset($form['url']) ? e107::getParser()->replaceConstants($form['url'], 'abs') : e_SELF).($query ? '?'.$query : ''); + + $text .= " + ".vartrue($form['form_pre'])." +
+
+ ".vartrue($form['header'])." + ".$this->token()." + "; + + foreach ($form['fieldsets'] as $elid => $fieldset_data) + { + $elid = $form['id'].'-'.$elid; + $text .= $this->renderFieldset($elid, $fieldset_data); + } + + $text .= " + ".vartrue($form['footer'])." +
+
+ ".vartrue($form['form_post'])." + "; + } + if(!$nocontainer) + { + $text = '
'.$text.'
'; + } + return $text; + } + + /** + * Generic renderFieldset solution, will be split to renderTable, renderCol/Row/Box etc - Still in use. + */ + function renderFieldset($id, $fdata) + { + $colgroup = ''; + if(vartrue($fdata['table_colgroup'])) + { + $colgroup = " + + "; + foreach ($fdata['table_colgroup'] as $i => $colgr) + { + $colgroup .= " $v) + { + $colgroup .= "{$attr}='{$v}'"; + } + $colgroup .= " /> + "; + } + + $colgroup = " + "; + } + $text = vartrue($fdata['fieldset_pre'])." +
+ ".vartrue($fdata['legend'])." + ".vartrue($fdata['table_pre'])." + + "; + + if(vartrue($fdata['table_rows']) || vartrue($fdata['table_body'])) + { + $text .= " + + {$colgroup} + + ".vartrue($fdata['table_head'])." + + + "; + + if(vartrue($fdata['table_rows'])) + { + foreach($fdata['table_rows'] as $index => $row) + { + $text .= " + + $row + + "; + } + } + elseif(vartrue($fdata['table_body'])) + { + $text .= $fdata['table_body']; + } + + if(vartrue($fdata['table_note'])) + { + $note = '
'.$fdata['table_note'].'
'; + } + + $text .= " + +
+ ".$note." + ".vartrue($fdata['table_post'])." + "; + } + + $triggers = vartrue($fdata['triggers'], array()); + if($triggers) + { + $text .= "
+ ".vartrue($fdata['pre_triggers'], '')." + "; + foreach ($triggers as $trigger => $tdata) + { + if(is_string($tdata)) + { + $text .= $tdata; + continue; + } + $text .= $this->admin_button('etrigger_'.$trigger, $tdata[0], $tdata[1]); + if(isset($tdata[2])) + { + $text .= $this->hidden($trigger.'_value', $tdata[2]); + } + } + $text .= "
"; + } + + $text .= " +
+ ".vartrue($fdata['fieldset_post'])." + "; + return $text; + } + + /** + * Render Value Trigger - override to modify field/value/parameters + * @param string $field field name + * @param mixed $value field value + * @param array $params 'writeParams' key (see $controller->fields array) + * @param int $id record ID + */ + public function renderValueTrigger(&$field, &$value, &$params, $id) + { + + } + + /** + * Render Element Trigger - override to modify field/value/parameters/validation data + * @param string $field field name + * @param mixed $value field value + * @param array $params 'writeParams' key (see $controller->fields array) + * @param array $required_data validation data + * @param int $id record ID + */ + public function renderElementTrigger(&$field, &$value, &$params, &$required_data, $id) + { + + } +} + +// DEPRECATED - use above methods instead ($frm) +class form +{ + function form_open($form_method, $form_action, $form_name = "", $form_target = "", $form_enctype = "", $form_js = "") + { + $method = ($form_method ? "method='".$form_method."'" : ""); + $target = ($form_target ? " target='".$form_target."'" : ""); + $name = ($form_name ? " id='".$form_name."' " : " id='myform'"); + return "\n
".e107::getForm()->token()."
"; + } + + function form_text($form_name, $form_size, $form_value, $form_maxlength = FALSE, $form_class = "tbox form-control", $form_readonly = "", $form_tooltip = "", $form_js = "") { + $name = ($form_name ? " id='".$form_name."' name='".$form_name."'" : ""); + $value = (isset($form_value) ? " value='".$form_value."'" : ""); + $size = ($form_size ? " size='".$form_size."'" : ""); + $maxlength = ($form_maxlength ? " maxlength='".$form_maxlength."'" : ""); + $readonly = ($form_readonly ? " readonly='readonly'" : ""); + $tooltip = ($form_tooltip ? " title='".$form_tooltip."'" : ""); + return "\n"; + } + + function form_password($form_name, $form_size, $form_value, $form_maxlength = FALSE, $form_class = "tbox form-control", $form_readonly = "", $form_tooltip = "", $form_js = "") { + $name = ($form_name ? " id='".$form_name."' name='".$form_name."'" : ""); + $value = (isset($form_value) ? " value='".$form_value."'" : ""); + $size = ($form_size ? " size='".$form_size."'" : ""); + $maxlength = ($form_maxlength ? " maxlength='".$form_maxlength."'" : ""); + $readonly = ($form_readonly ? " readonly='readonly'" : ""); + $tooltip = ($form_tooltip ? " title='".$form_tooltip."'" : ""); + return "\n"; + } + + function form_button($form_type, $form_name, $form_value, $form_js = "", $form_image = "", $form_tooltip = "") { + $name = ($form_name ? " id='".$form_name."' name='".$form_name."'" : ""); + $image = ($form_image ? " src='".$form_image."' " : ""); + $tooltip = ($form_tooltip ? " title='".$form_tooltip."' " : ""); + return "\n"; + } + + function form_textarea($form_name, $form_columns, $form_rows, $form_value, $form_js = "", $form_style = "", $form_wrap = "", $form_readonly = "", $form_tooltip = "") { + $name = ($form_name ? " id='".$form_name."' name='".$form_name."'" : ""); + $readonly = ($form_readonly ? " readonly='readonly'" : ""); + $tooltip = ($form_tooltip ? " title='".$form_tooltip."'" : ""); + $wrap = ($form_wrap ? " wrap='".$form_wrap."'" : ""); + $style = ($form_style ? " style='".$form_style."'" : ""); + return "\n"; + } + + function form_checkbox($form_name, $form_value, $form_checked = 0, $form_tooltip = "", $form_js = "") { + $name = ($form_name ? " id='".$form_name.$form_value."' name='".$form_name."'" : ""); + $checked = ($form_checked ? " checked='checked'" : ""); + $tooltip = ($form_tooltip ? " title='".$form_tooltip."'" : ""); + return "\n"; + + } + + function form_radio($form_name, $form_value, $form_checked = 0, $form_tooltip = "", $form_js = "") { + $name = ($form_name ? " id='".$form_name.$form_value."' name='".$form_name."'" : ""); + $checked = ($form_checked ? " checked='checked'" : ""); + $tooltip = ($form_tooltip ? " title='".$form_tooltip."'" : ""); + return "\n"; + + } + + function form_file($form_name, $form_size, $form_tooltip = "", $form_js = "") { + $name = ($form_name ? " id='".$form_name."' name='".$form_name."'" : ""); + $tooltip = ($form_tooltip ? " title='".$form_tooltip."'" : ""); + return ""; + } + + function form_select_open($form_name, $form_js = "") { + return "\n"; + } + + function form_option($form_option, $form_selected = "", $form_value = "", $form_js = "") { + $value = ($form_value !== FALSE ? " value='".$form_value."'" : ""); + $selected = ($form_selected ? " selected='selected'" : ""); + return "\n".$form_option.""; + } + + function form_hidden($form_name, $form_value) { + return "\n"; + } + + function form_close() { + return "\n"; + } +} + +/* +Usage +echo $rs->form_open("post", e_SELF, "_blank"); +echo $rs->form_text("testname", 100, "this is the value", 100, 0, "tooltip"); +echo $rs->form_button("submit", "testsubmit", "SUBMIT!", "", "Click to submit"); +echo $rs->form_button("reset", "testreset", "RESET!", "", "Click to reset"); +echo $rs->form_textarea("textareaname", 10, 10, "Value", "overflow:hidden"); +echo $rs->form_checkbox("testcheckbox", 1, 1); +echo $rs->form_checkbox("testcheckbox2", 2); +echo $rs->form_hidden("hiddenname", "hiddenvalue"); +echo $rs->form_radio("testcheckbox", 1, 1); +echo $rs->form_radio("testcheckbox", 1); +echo $rs->form_file("testfile", "20"); +echo $rs->form_select_open("testselect"); +echo $rs->form_option("Option 1"); +echo $rs->form_option("Option 2"); +echo $rs->form_option("Option 3", 1, "defaultvalue"); +echo $rs->form_option("Option 4"); +echo $rs->form_select_close(); +echo $rs->form_close(); +*/ + + +?> diff --git a/e107_handlers/hybridauth/Hybrid/Auth.php b/e107_handlers/hybridauth/Hybrid/Auth.php index a7991f709..5642b5091 100644 --- a/e107_handlers/hybridauth/Hybrid/Auth.php +++ b/e107_handlers/hybridauth/Hybrid/Auth.php @@ -1,414 +1,414 @@ -getSessionData()); - Hybrid_Logger::info("Hybrid_Auth initialize: check if any error is stored on the endpoint..."); - - if (Hybrid_Error::hasError()) { - $m = Hybrid_Error::getErrorMessage(); - $c = Hybrid_Error::getErrorCode(); - $p = Hybrid_Error::getErrorPrevious(); - - Hybrid_Logger::error("Hybrid_Auth initialize: A stored Error found, Throw an new Exception and delete it from the store: Error#$c, '$m'"); - - Hybrid_Error::clearError(); - - // try to provide the previous if any - // Exception::getPrevious (PHP 5 >= 5.3.0) http://php.net/manual/en/exception.getprevious.php - if (version_compare(PHP_VERSION, '5.3.0', '>=') && ($p instanceof Exception)) { - throw new Exception($m, $c, $p); - } else { - throw new Exception($m, $c); - } - } - - Hybrid_Logger::info("Hybrid_Auth initialize: no error found. initialization succeed."); - } - - /** - * Hybrid storage system accessor - * - * Users sessions are stored using HybridAuth storage system ( HybridAuth 2.0 handle PHP Session only) and can be accessed directly by - * Hybrid_Auth::storage()->get($key) to retrieves the data for the given key, or calling - * Hybrid_Auth::storage()->set($key, $value) to store the key => $value set. - * - * @return Hybrid_Storage - */ - public static function storage() { - return Hybrid_Auth::$store; - } - - /** - * Get hybridauth session data - * @return string|null - */ - function getSessionData() { - return Hybrid_Auth::storage()->getSessionData(); - } - - /** - * Restore hybridauth session data - * - * @param string $sessiondata Serialized session data - * @retun void - */ - function restoreSessionData($sessiondata = null) { - Hybrid_Auth::storage()->restoreSessionData($sessiondata); - } - - /** - * Try to authenticate the user with a given provider. - * - * If the user is already connected we just return and instance of provider adapter, - * ELSE, try to authenticate and authorize the user with the provider. - * - * $params is generally an array with required info in order for this provider and HybridAuth to work, - * like : - * hauth_return_to: URL to call back after authentication is done - * openid_identifier: The OpenID identity provider identifier - * google_service: can be "Users" for Google user accounts service or "Apps" for Google hosted Apps - * - * @param string $providerId ID of the provider - * @param array $params Params - * @return - */ - public static function authenticate($providerId, $params = null) { - Hybrid_Logger::info("Enter Hybrid_Auth::authenticate( $providerId )"); - - if (!Hybrid_Auth::storage()->get("hauth_session.$providerId.is_logged_in")) { - // if user not connected to $providerId then try setup a new adapter and start the login process for this provider - Hybrid_Logger::info("Hybrid_Auth::authenticate( $providerId ), User not connected to the provider. Try to authenticate.."); - $provider_adapter = Hybrid_Auth::setup($providerId, $params); - $provider_adapter->login(); - } else { - // else, then return the adapter instance for the given provider - Hybrid_Logger::info("Hybrid_Auth::authenticate( $providerId ), User is already connected to this provider. Return the adapter instance."); - return Hybrid_Auth::getAdapter($providerId); - } - } - - /** - * Return the adapter instance for an authenticated provider - * - * @param string $providerId ID of the provider - * @return Hybrid_Provider_Adapter - */ - public static function getAdapter($providerId = null) { - Hybrid_Logger::info("Enter Hybrid_Auth::getAdapter( $providerId )"); - return Hybrid_Auth::setup($providerId); - } - - /** - * Setup an adapter for a given provider - * - * @param string $providerId ID of the provider - * @param array $params Adapter params - * @return Hybrid_Provider_Adapter - */ - public static function setup($providerId, $params = null) { - Hybrid_Logger::debug("Enter Hybrid_Auth::setup( $providerId )", $params); - - if (!$params) { - $params = Hybrid_Auth::storage()->get("hauth_session.$providerId.id_provider_params"); - - Hybrid_Logger::debug("Hybrid_Auth::setup( $providerId ), no params given. Trying to get the stored for this provider.", $params); - } - - if (!$params) { - $params = array(); - Hybrid_Logger::info("Hybrid_Auth::setup( $providerId ), no stored params found for this provider. Initialize a new one for new session"); - } - - if (is_array($params) && !isset($params["hauth_return_to"])) { - $params["hauth_return_to"] = Hybrid_Auth::getCurrentUrl(); - Hybrid_Logger::debug("Hybrid_Auth::setup( $providerId ). HybridAuth Callback URL set to: ", $params["hauth_return_to"]); - } - - # instantiate a new IDProvider Adapter - $provider = new Hybrid_Provider_Adapter(); - $provider->factory($providerId, $params); - return $provider; - } - - /** - * Check if the current user is connected to a given provider - * - * @param string $providerId ID of the provider - * @return bool - */ - public static function isConnectedWith($providerId) { - return (bool) Hybrid_Auth::storage()->get("hauth_session.{$providerId}.is_logged_in"); - } - - /** - * Return array listing all authenticated providers - * @return array - */ - public static function getConnectedProviders() { - $idps = array(); - - foreach (Hybrid_Auth::$config["providers"] as $idpid => $params) { - if (Hybrid_Auth::isConnectedWith($idpid)) { - $idps[] = $idpid; - } - } - - return $idps; - } - - /** - * Return array listing all enabled providers as well as a flag if you are connected - * - * - * array( - * 'Facebook' => array( - * 'connected' => true - * ) - * ) - * - * @return array - */ - public static function getProviders() { - $idps = array(); - - foreach (Hybrid_Auth::$config["providers"] as $idpid => $params) { - if ($params['enabled']) { - $idps[$idpid] = array('connected' => false); - - if (Hybrid_Auth::isConnectedWith($idpid)) { - $idps[$idpid]['connected'] = true; - } - } - } - - return $idps; - } - - /** - * A generic function to logout all connected provider at once - * @return void - */ - public static function logoutAllProviders() { - $idps = Hybrid_Auth::getConnectedProviders(); - - foreach ($idps as $idp) { - $adapter = Hybrid_Auth::getAdapter($idp); - $adapter->logout(); - } - } - - /** - * Utility function, redirect to a given URL with php header or using javascript location.href - * - * @param string $url URL to redirect to - * @param string $mode PHP|JS - */ - public static function redirect($url, $mode = "PHP") { - if(!$mode){ - $mode = 'PHP'; - } - Hybrid_Logger::info("Enter Hybrid_Auth::redirect( $url, $mode )"); - - // Ensure session is saved before sending response, see https://github.com/symfony/symfony/pull/12341 - if ((PHP_VERSION_ID >= 50400 && PHP_SESSION_ACTIVE === session_status()) || (PHP_VERSION_ID < 50400 && isset($_SESSION) && session_id())) { - session_write_close(); - } - - if ($mode == "PHP") { - header("Location: $url"); - } elseif ($mode == "JS") { - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo 'Redirecting, please wait...'; - echo ''; - echo ''; - } - - die(); - } - - /** - * Utility function, return the current url - * - * @param bool $request_uri true to get $_SERVER['REQUEST_URI'], false for $_SERVER['PHP_SELF'] - * @return string - */ - public static function getCurrentUrl($request_uri = true) { - if (php_sapi_name() == 'cli') { - return ''; - } - - $protocol = 'http://'; - - if ((isset($_SERVER['HTTPS']) && ( $_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1 )) - || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) - { - $protocol = 'https://'; - } - - $url = $protocol . $_SERVER['HTTP_HOST']; - - if ($request_uri) { - $url .= $_SERVER['REQUEST_URI']; - } else { - $url .= $_SERVER['PHP_SELF']; - } - - // return current url - return $url; - } - -} +getSessionData()); + Hybrid_Logger::info("Hybrid_Auth initialize: check if any error is stored on the endpoint..."); + + if (Hybrid_Error::hasError()) { + $m = Hybrid_Error::getErrorMessage(); + $c = Hybrid_Error::getErrorCode(); + $p = Hybrid_Error::getErrorPrevious(); + + Hybrid_Logger::error("Hybrid_Auth initialize: A stored Error found, Throw an new Exception and delete it from the store: Error#$c, '$m'"); + + Hybrid_Error::clearError(); + + // try to provide the previous if any + // Exception::getPrevious (PHP 5 >= 5.3.0) http://php.net/manual/en/exception.getprevious.php + if (version_compare(PHP_VERSION, '5.3.0', '>=') && ($p instanceof Exception)) { + throw new Exception($m, $c, $p); + } else { + throw new Exception($m, $c); + } + } + + Hybrid_Logger::info("Hybrid_Auth initialize: no error found. initialization succeed."); + } + + /** + * Hybrid storage system accessor + * + * Users sessions are stored using HybridAuth storage system ( HybridAuth 2.0 handle PHP Session only) and can be accessed directly by + * Hybrid_Auth::storage()->get($key) to retrieves the data for the given key, or calling + * Hybrid_Auth::storage()->set($key, $value) to store the key => $value set. + * + * @return Hybrid_Storage + */ + public static function storage() { + return Hybrid_Auth::$store; + } + + /** + * Get hybridauth session data + * @return string|null + */ + function getSessionData() { + return Hybrid_Auth::storage()->getSessionData(); + } + + /** + * Restore hybridauth session data + * + * @param string $sessiondata Serialized session data + * @retun void + */ + function restoreSessionData($sessiondata = null) { + Hybrid_Auth::storage()->restoreSessionData($sessiondata); + } + + /** + * Try to authenticate the user with a given provider. + * + * If the user is already connected we just return and instance of provider adapter, + * ELSE, try to authenticate and authorize the user with the provider. + * + * $params is generally an array with required info in order for this provider and HybridAuth to work, + * like : + * hauth_return_to: URL to call back after authentication is done + * openid_identifier: The OpenID identity provider identifier + * google_service: can be "Users" for Google user accounts service or "Apps" for Google hosted Apps + * + * @param string $providerId ID of the provider + * @param array $params Params + * @return + */ + public static function authenticate($providerId, $params = null) { + Hybrid_Logger::info("Enter Hybrid_Auth::authenticate( $providerId )"); + + if (!Hybrid_Auth::storage()->get("hauth_session.$providerId.is_logged_in")) { + // if user not connected to $providerId then try setup a new adapter and start the login process for this provider + Hybrid_Logger::info("Hybrid_Auth::authenticate( $providerId ), User not connected to the provider. Try to authenticate.."); + $provider_adapter = Hybrid_Auth::setup($providerId, $params); + $provider_adapter->login(); + } else { + // else, then return the adapter instance for the given provider + Hybrid_Logger::info("Hybrid_Auth::authenticate( $providerId ), User is already connected to this provider. Return the adapter instance."); + return Hybrid_Auth::getAdapter($providerId); + } + } + + /** + * Return the adapter instance for an authenticated provider + * + * @param string $providerId ID of the provider + * @return Hybrid_Provider_Adapter + */ + public static function getAdapter($providerId = null) { + Hybrid_Logger::info("Enter Hybrid_Auth::getAdapter( $providerId )"); + return Hybrid_Auth::setup($providerId); + } + + /** + * Setup an adapter for a given provider + * + * @param string $providerId ID of the provider + * @param array $params Adapter params + * @return Hybrid_Provider_Adapter + */ + public static function setup($providerId, $params = null) { + Hybrid_Logger::debug("Enter Hybrid_Auth::setup( $providerId )", $params); + + if (!$params) { + $params = Hybrid_Auth::storage()->get("hauth_session.$providerId.id_provider_params"); + + Hybrid_Logger::debug("Hybrid_Auth::setup( $providerId ), no params given. Trying to get the stored for this provider.", $params); + } + + if (!$params) { + $params = array(); + Hybrid_Logger::info("Hybrid_Auth::setup( $providerId ), no stored params found for this provider. Initialize a new one for new session"); + } + + if (is_array($params) && !isset($params["hauth_return_to"])) { + $params["hauth_return_to"] = Hybrid_Auth::getCurrentUrl(); + Hybrid_Logger::debug("Hybrid_Auth::setup( $providerId ). HybridAuth Callback URL set to: ", $params["hauth_return_to"]); + } + + # instantiate a new IDProvider Adapter + $provider = new Hybrid_Provider_Adapter(); + $provider->factory($providerId, $params); + return $provider; + } + + /** + * Check if the current user is connected to a given provider + * + * @param string $providerId ID of the provider + * @return bool + */ + public static function isConnectedWith($providerId) { + return (bool) Hybrid_Auth::storage()->get("hauth_session.{$providerId}.is_logged_in"); + } + + /** + * Return array listing all authenticated providers + * @return array + */ + public static function getConnectedProviders() { + $idps = array(); + + foreach (Hybrid_Auth::$config["providers"] as $idpid => $params) { + if (Hybrid_Auth::isConnectedWith($idpid)) { + $idps[] = $idpid; + } + } + + return $idps; + } + + /** + * Return array listing all enabled providers as well as a flag if you are connected + * + * + * array( + * 'Facebook' => array( + * 'connected' => true + * ) + * ) + * + * @return array + */ + public static function getProviders() { + $idps = array(); + + foreach (Hybrid_Auth::$config["providers"] as $idpid => $params) { + if ($params['enabled']) { + $idps[$idpid] = array('connected' => false); + + if (Hybrid_Auth::isConnectedWith($idpid)) { + $idps[$idpid]['connected'] = true; + } + } + } + + return $idps; + } + + /** + * A generic function to logout all connected provider at once + * @return void + */ + public static function logoutAllProviders() { + $idps = Hybrid_Auth::getConnectedProviders(); + + foreach ($idps as $idp) { + $adapter = Hybrid_Auth::getAdapter($idp); + $adapter->logout(); + } + } + + /** + * Utility function, redirect to a given URL with php header or using javascript location.href + * + * @param string $url URL to redirect to + * @param string $mode PHP|JS + */ + public static function redirect($url, $mode = "PHP") { + if(!$mode){ + $mode = 'PHP'; + } + Hybrid_Logger::info("Enter Hybrid_Auth::redirect( $url, $mode )"); + + // Ensure session is saved before sending response, see https://github.com/symfony/symfony/pull/12341 + if ((PHP_VERSION_ID >= 50400 && PHP_SESSION_ACTIVE === session_status()) || (PHP_VERSION_ID < 50400 && isset($_SESSION) && session_id())) { + session_write_close(); + } + + if ($mode == "PHP") { + header("Location: $url"); + } elseif ($mode == "JS") { + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo 'Redirecting, please wait...'; + echo ''; + echo ''; + } + + die(); + } + + /** + * Utility function, return the current url + * + * @param bool $request_uri true to get $_SERVER['REQUEST_URI'], false for $_SERVER['PHP_SELF'] + * @return string + */ + public static function getCurrentUrl($request_uri = true) { + if (php_sapi_name() == 'cli') { + return ''; + } + + $protocol = 'http://'; + + if ((isset($_SERVER['HTTPS']) && ( $_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1 )) + || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) + { + $protocol = 'https://'; + } + + $url = $protocol . $_SERVER['HTTP_HOST']; + + if ($request_uri) { + $url .= $_SERVER['REQUEST_URI']; + } else { + $url .= $_SERVER['PHP_SELF']; + } + + // return current url + return $url; + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Error.php b/e107_handlers/hybridauth/Hybrid/Error.php index 7013b4976..e9c319c68 100644 --- a/e107_handlers/hybridauth/Hybrid/Error.php +++ b/e107_handlers/hybridauth/Hybrid/Error.php @@ -1,88 +1,88 @@ -set("hauth_session.error.status", 1); - Hybrid_Auth::storage()->set("hauth_session.error.message", $message); - Hybrid_Auth::storage()->set("hauth_session.error.code", $code); - Hybrid_Auth::storage()->set("hauth_session.error.trace", $trace); - Hybrid_Auth::storage()->set("hauth_session.error.previous", $previous); - } - - /** - * Clear the last error - * @return void - */ - public static function clearError() { - Hybrid_Logger::info("Enter Hybrid_Error::clearError()"); - - Hybrid_Auth::storage()->delete("hauth_session.error.status"); - Hybrid_Auth::storage()->delete("hauth_session.error.message"); - Hybrid_Auth::storage()->delete("hauth_session.error.code"); - Hybrid_Auth::storage()->delete("hauth_session.error.trace"); - Hybrid_Auth::storage()->delete("hauth_session.error.previous"); - } - - /** - * Checks to see if there is a an error. - * @return boolean true if there is an error. - */ - public static function hasError() { - return (bool) Hybrid_Auth::storage()->get("hauth_session.error.status"); - } - - /** - * Return error message - * @return string - */ - public static function getErrorMessage() { - return Hybrid_Auth::storage()->get("hauth_session.error.message"); - } - - /** - * Return error code - * @return int - */ - public static function getErrorCode() { - return Hybrid_Auth::storage()->get("hauth_session.error.code"); - } - - /** - * Return string detailed error backtrace as string - * @return string - */ - public static function getErrorTrace() { - return Hybrid_Auth::storage()->get("hauth_session.error.trace"); - } - - /** - * Detailed error backtrace as string - * @return string - */ - public static function getErrorPrevious() { - return Hybrid_Auth::storage()->get("hauth_session.error.previous"); - } - -} +set("hauth_session.error.status", 1); + Hybrid_Auth::storage()->set("hauth_session.error.message", $message); + Hybrid_Auth::storage()->set("hauth_session.error.code", $code); + Hybrid_Auth::storage()->set("hauth_session.error.trace", $trace); + Hybrid_Auth::storage()->set("hauth_session.error.previous", $previous); + } + + /** + * Clear the last error + * @return void + */ + public static function clearError() { + Hybrid_Logger::info("Enter Hybrid_Error::clearError()"); + + Hybrid_Auth::storage()->delete("hauth_session.error.status"); + Hybrid_Auth::storage()->delete("hauth_session.error.message"); + Hybrid_Auth::storage()->delete("hauth_session.error.code"); + Hybrid_Auth::storage()->delete("hauth_session.error.trace"); + Hybrid_Auth::storage()->delete("hauth_session.error.previous"); + } + + /** + * Checks to see if there is a an error. + * @return boolean true if there is an error. + */ + public static function hasError() { + return (bool) Hybrid_Auth::storage()->get("hauth_session.error.status"); + } + + /** + * Return error message + * @return string + */ + public static function getErrorMessage() { + return Hybrid_Auth::storage()->get("hauth_session.error.message"); + } + + /** + * Return error code + * @return int + */ + public static function getErrorCode() { + return Hybrid_Auth::storage()->get("hauth_session.error.code"); + } + + /** + * Return string detailed error backtrace as string + * @return string + */ + public static function getErrorTrace() { + return Hybrid_Auth::storage()->get("hauth_session.error.trace"); + } + + /** + * Detailed error backtrace as string + * @return string + */ + public static function getErrorPrevious() { + return Hybrid_Auth::storage()->get("hauth_session.error.previous"); + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Logger.php b/e107_handlers/hybridauth/Hybrid/Logger.php index f948913da..eeca3bd59 100644 --- a/e107_handlers/hybridauth/Hybrid/Logger.php +++ b/e107_handlers/hybridauth/Hybrid/Logger.php @@ -1,102 +1,102 @@ -format(DATE_ATOM), - $message, - print_r($object, true) . PHP_EOL, - )), FILE_APPEND - ); - } - } - - /** - * Logs an info message - * - * @param string $message Info message - * @return void - */ - public static function info($message) { - if (in_array(Hybrid_Auth::$config["debug_mode"], array(true, 'info'), true)) { - $dt = new DateTime('now', new DateTimeZone( 'UTC' )); - file_put_contents(Hybrid_Auth::$config["debug_file"], implode(' -- ', array( - "INFO", - $_SERVER['REMOTE_ADDR'], - $dt->format(DATE_ATOM), - $message . PHP_EOL, - )), FILE_APPEND); - } - } - - /** - * Logs an error message with an object dump - * - * @param string $message Error message - * @param stdClass $object Object being debugged - * @return void - */ - public static function error($message, $object = null) { - if (isset(Hybrid_Auth::$config["debug_mode"]) && in_array(Hybrid_Auth::$config["debug_mode"], array(true, 'info', 'error'), true)) { - $dt = new DateTime('now', new DateTimeZone( 'UTC' )); - file_put_contents(Hybrid_Auth::$config["debug_file"], implode(' -- ', array( - 'ERROR', - $_SERVER['REMOTE_ADDR'], - $dt->format(DATE_ATOM), - $message, - print_r($object, true) . PHP_EOL - )), FILE_APPEND); - } - } - - /** - * Dumps the data in the way suitable to be output in log files for debug purposes - * - * @param mixed $data - * - * @return string - */ - public static function dumpData($data) { - return var_export($data, true); - } - -} +format(DATE_ATOM), + $message, + print_r($object, true) . PHP_EOL, + )), FILE_APPEND + ); + } + } + + /** + * Logs an info message + * + * @param string $message Info message + * @return void + */ + public static function info($message) { + if (in_array(Hybrid_Auth::$config["debug_mode"], array(true, 'info'), true)) { + $dt = new DateTime('now', new DateTimeZone( 'UTC' )); + file_put_contents(Hybrid_Auth::$config["debug_file"], implode(' -- ', array( + "INFO", + $_SERVER['REMOTE_ADDR'], + $dt->format(DATE_ATOM), + $message . PHP_EOL, + )), FILE_APPEND); + } + } + + /** + * Logs an error message with an object dump + * + * @param string $message Error message + * @param stdClass $object Object being debugged + * @return void + */ + public static function error($message, $object = null) { + if (isset(Hybrid_Auth::$config["debug_mode"]) && in_array(Hybrid_Auth::$config["debug_mode"], array(true, 'info', 'error'), true)) { + $dt = new DateTime('now', new DateTimeZone( 'UTC' )); + file_put_contents(Hybrid_Auth::$config["debug_file"], implode(' -- ', array( + 'ERROR', + $_SERVER['REMOTE_ADDR'], + $dt->format(DATE_ATOM), + $message, + print_r($object, true) . PHP_EOL + )), FILE_APPEND); + } + } + + /** + * Dumps the data in the way suitable to be output in log files for debug purposes + * + * @param mixed $data + * + * @return string + */ + public static function dumpData($data) { + return var_export($data, true); + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Provider_Adapter.php b/e107_handlers/hybridauth/Hybrid/Provider_Adapter.php index f96a500b1..aeeb30bb2 100644 --- a/e107_handlers/hybridauth/Hybrid/Provider_Adapter.php +++ b/e107_handlers/hybridauth/Hybrid/Provider_Adapter.php @@ -1,340 +1,340 @@ -id = $id; - $this->params = $params; - $this->id = $this->getProviderCiId($this->id); - $this->config = $this->getConfigById($this->id); - - # check the IDp id - if (!$this->id) { - throw new Exception("No provider ID specified.", 2); - } - - # check the IDp config - if (!$this->config) { - throw new Exception("Unknown Provider ID, check your configuration file.", 3); - } - - # check the IDp adapter is enabled - if (!$this->config["enabled"]) { - throw new Exception("The provider '{$this->id}' is not enabled.", 3); - } - - # include the adapter wrapper - if (isset($this->config["wrapper"]) && is_array($this->config["wrapper"])) { - if (isset($this->config["wrapper"]["path"])) { - require_once $this->config["wrapper"]["path"]; - } - - if (!class_exists($this->config["wrapper"]["class"])) { - throw new Exception("Unable to load the adapter class.", 3); - } - - $this->wrapper = $this->config["wrapper"]["class"]; - } else { - require_once Hybrid_Auth::$config["path_providers"] . $this->id . ".php"; - - $this->wrapper = "Hybrid_Providers_" . $this->id; - } - - # create the adapter instance, and pass the current params and config - $this->adapter = new $this->wrapper($this->id, $this->config, $this->params); - - return $this; - } - - /** - * Hybrid_Provider_Adapter::login(), prepare the user session and the authentication request - * for index.php - * @return void - * @throw Exception - */ - function login() { - Hybrid_Logger::info("Enter Hybrid_Provider_Adapter::login( {$this->id} ) "); - - if (!$this->adapter) { - throw new Exception("Hybrid_Provider_Adapter::login() should not directly used."); - } - - // clear all unneeded params - foreach (Hybrid_Auth::$config["providers"] as $idpid => $params) { - Hybrid_Auth::storage()->delete("hauth_session.{$idpid}.hauth_return_to"); - Hybrid_Auth::storage()->delete("hauth_session.{$idpid}.hauth_endpoint"); - Hybrid_Auth::storage()->delete("hauth_session.{$idpid}.id_provider_params"); - } - - // make a fresh start - $this->logout(); - - # get hybridauth base url - if (empty(Hybrid_Auth::$config["base_url"])) { - // the base url wasn't provide, so we must use the current - // url (which makes sense actually) - $url = empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == 'off' ? 'http' : 'https'; - $url .= '://' . $_SERVER['HTTP_HOST']; - $url .= $_SERVER['REQUEST_URI']; - $HYBRID_AUTH_URL_BASE = $url; - } else { - $HYBRID_AUTH_URL_BASE = Hybrid_Auth::$config["base_url"]; - } - - // make sure params is array - if (!is_array($this->params)) { - $this->params = array(); - } - - # we make use of session_id() as storage hash to identify the current user - # using session_regenerate_id() will be a problem, but .. - $this->params["hauth_token"] = session_id(); - - # set request timestamp - $this->params["hauth_time"] = time(); - - # for default HybridAuth endpoint url hauth_login_start_url - # auth.start required the IDp ID - # auth.time optional login request timestamp - if (!isset($this->params["login_start"]) ) { - $this->params["login_start"] = $HYBRID_AUTH_URL_BASE . ( strpos($HYBRID_AUTH_URL_BASE, '?') ? '&' : '?' ) . "hauth.start={$this->id}&hauth.time={$this->params["hauth_time"]}"; - } - - # for default HybridAuth endpoint url hauth_login_done_url - # auth.done required the IDp ID - if (!isset($this->params["login_done"]) ) { - $this->params["login_done"] = $HYBRID_AUTH_URL_BASE . ( strpos($HYBRID_AUTH_URL_BASE, '?') ? '&' : '?' ) . "hauth.done={$this->id}"; - } - - # workaround to solve windows live authentication since microsoft disallowed redirect urls to contain any parameters - # http://mywebsite.com/path_to_hybridauth/?hauth.done=Live will not work - if ($this->id=="Live") { - $this->params["login_done"] = $HYBRID_AUTH_URL_BASE."live.php"; - } - - # Workaround to fix broken callback urls for the Facebook OAuth client - if ($this->adapter->useSafeUrls) { - $this->params['login_done'] = str_replace('hauth.done', 'hauth_done', $this->params['login_done']); - } - - if (isset($this->params["hauth_return_to"])) { - Hybrid_Auth::storage()->set("hauth_session.{$this->id}.hauth_return_to", $this->params["hauth_return_to"]); - } - if (isset($this->params["login_done"])) { - Hybrid_Auth::storage()->set("hauth_session.{$this->id}.hauth_endpoint", $this->params["login_done"]); - } - Hybrid_Auth::storage()->set("hauth_session.{$this->id}.id_provider_params", $this->params); - - // store config to be used by the end point - Hybrid_Auth::storage()->config("CONFIG", Hybrid_Auth::$config); - - // move on - Hybrid_Logger::debug("Hybrid_Provider_Adapter::login( {$this->id} ), redirect the user to login_start URL."); - - // redirect - if (empty($this->params["redirect_mode"])) { - Hybrid_Auth::redirect($this->params["login_start"]); - } else { - Hybrid_Auth::redirect($this->params["login_start"],$this->params["redirect_mode"]); - } - } - - /** - * Let hybridauth forget all about the user for the current provider - * @return bool - */ - function logout() { - $this->adapter->logout(); - } - - // -------------------------------------------------------------------- - - /** - * Return true if the user is connected to the current provider - * @return bool - */ - public function isUserConnected() { - return $this->adapter->isUserConnected(); - } - - // -------------------------------------------------------------------- - - /** - * Call adapter methods defined in the adapter model: - * getUserProfile() - * getUserContacts() - * getUserActivity() - * setUserStatus() - * - * @param string $name Method name - * @param array $arguments Call arguments - * @return mixed - * @throws Exception - */ - public function __call($name, $arguments) { - Hybrid_Logger::info("Enter Hybrid_Provider_Adapter::$name(), Provider: {$this->id}"); - - if (!$this->isUserConnected()) { - throw new Exception("User not connected to the provider {$this->id}.", 7); - } - - if (!method_exists($this->adapter, $name)) { - throw new Exception("Call to undefined function Hybrid_Providers_{$this->id}::$name()."); - } - - return call_user_func_array(array($this->adapter, $name), $arguments); - } - - /** - * If the user is connected, then return the access_token and access_token_secret - * if the provider api use oauth - * - * - * array( - * 'access_token' => '', - * 'access_token_secret' => '', - * 'refresh_token' => '', - * 'expires_in' => '', - * 'expires_at' => '', - * ) - * - * @return array - */ - public function getAccessToken() { - if (!$this->adapter->isUserConnected()) { - Hybrid_Logger::error("User not connected to the provider."); - throw new Exception("User not connected to the provider.", 7); - } - - return array( - "access_token" => $this->adapter->token("access_token"), // OAuth access token - "access_token_secret" => $this->adapter->token("access_token_secret"), // OAuth access token secret - "refresh_token" => $this->adapter->token("refresh_token"), // OAuth refresh token - "expires_in" => $this->adapter->token("expires_in"), // OPTIONAL. The duration in seconds of the access token lifetime - "expires_at" => $this->adapter->token("expires_at"), // OPTIONAL. Timestamp when the access_token expire. if not provided by the social api, then it should be calculated: expires_at = now + expires_in - ); - } - - /** - * Naive getter of the current connected IDp API client - * @return stdClass - * @throws Exception - */ - function api() { - if (!$this->adapter->isUserConnected()) { - Hybrid_Logger::error("User not connected to the provider."); - - throw new Exception("User not connected to the provider.", 7); - } - return $this->adapter->api; - } - - /** - * Redirect the user to hauth_return_to (the callback url) - * @return void - */ - function returnToCallbackUrl() { - // get the stored callback url - $callback_url = Hybrid_Auth::storage()->get("hauth_session.{$this->id}.hauth_return_to"); - - // if the user presses the back button in the browser and we already deleted the hauth_return_to from - // the session in the previous request, we will redirect to '/' instead of displaying a blank page. - if (!$callback_url) { - $callback_url = '/'; - } - - // remove some unneeded stored data - Hybrid_Auth::storage()->delete("hauth_session.{$this->id}.hauth_return_to"); - Hybrid_Auth::storage()->delete("hauth_session.{$this->id}.hauth_endpoint"); - Hybrid_Auth::storage()->delete("hauth_session.{$this->id}.id_provider_params"); - - // back to home - Hybrid_Auth::redirect($callback_url); - } - - /** - * Return the provider config by id - * - * @param string $id Config key - * @return mixed - */ - function getConfigById($id) { - if (isset(Hybrid_Auth::$config["providers"][$id])) { - return Hybrid_Auth::$config["providers"][$id]; - } - return null; - } - - /** - * Return the provider config by id; case insensitive - * - * @param string $id Provider id - * @return mixed - */ - function getProviderCiId($id) { - foreach (Hybrid_Auth::$config["providers"] as $idpid => $params) { - if (strtolower($idpid) == strtolower($id)) { - return $idpid; - } - } - return null; - } - -} +id = $id; + $this->params = $params; + $this->id = $this->getProviderCiId($this->id); + $this->config = $this->getConfigById($this->id); + + # check the IDp id + if (!$this->id) { + throw new Exception("No provider ID specified.", 2); + } + + # check the IDp config + if (!$this->config) { + throw new Exception("Unknown Provider ID, check your configuration file.", 3); + } + + # check the IDp adapter is enabled + if (!$this->config["enabled"]) { + throw new Exception("The provider '{$this->id}' is not enabled.", 3); + } + + # include the adapter wrapper + if (isset($this->config["wrapper"]) && is_array($this->config["wrapper"])) { + if (isset($this->config["wrapper"]["path"])) { + require_once $this->config["wrapper"]["path"]; + } + + if (!class_exists($this->config["wrapper"]["class"])) { + throw new Exception("Unable to load the adapter class.", 3); + } + + $this->wrapper = $this->config["wrapper"]["class"]; + } else { + require_once Hybrid_Auth::$config["path_providers"] . $this->id . ".php"; + + $this->wrapper = "Hybrid_Providers_" . $this->id; + } + + # create the adapter instance, and pass the current params and config + $this->adapter = new $this->wrapper($this->id, $this->config, $this->params); + + return $this; + } + + /** + * Hybrid_Provider_Adapter::login(), prepare the user session and the authentication request + * for index.php + * @return void + * @throw Exception + */ + function login() { + Hybrid_Logger::info("Enter Hybrid_Provider_Adapter::login( {$this->id} ) "); + + if (!$this->adapter) { + throw new Exception("Hybrid_Provider_Adapter::login() should not directly used."); + } + + // clear all unneeded params + foreach (Hybrid_Auth::$config["providers"] as $idpid => $params) { + Hybrid_Auth::storage()->delete("hauth_session.{$idpid}.hauth_return_to"); + Hybrid_Auth::storage()->delete("hauth_session.{$idpid}.hauth_endpoint"); + Hybrid_Auth::storage()->delete("hauth_session.{$idpid}.id_provider_params"); + } + + // make a fresh start + $this->logout(); + + # get hybridauth base url + if (empty(Hybrid_Auth::$config["base_url"])) { + // the base url wasn't provide, so we must use the current + // url (which makes sense actually) + $url = empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == 'off' ? 'http' : 'https'; + $url .= '://' . $_SERVER['HTTP_HOST']; + $url .= $_SERVER['REQUEST_URI']; + $HYBRID_AUTH_URL_BASE = $url; + } else { + $HYBRID_AUTH_URL_BASE = Hybrid_Auth::$config["base_url"]; + } + + // make sure params is array + if (!is_array($this->params)) { + $this->params = array(); + } + + # we make use of session_id() as storage hash to identify the current user + # using session_regenerate_id() will be a problem, but .. + $this->params["hauth_token"] = session_id(); + + # set request timestamp + $this->params["hauth_time"] = time(); + + # for default HybridAuth endpoint url hauth_login_start_url + # auth.start required the IDp ID + # auth.time optional login request timestamp + if (!isset($this->params["login_start"]) ) { + $this->params["login_start"] = $HYBRID_AUTH_URL_BASE . ( strpos($HYBRID_AUTH_URL_BASE, '?') ? '&' : '?' ) . "hauth.start={$this->id}&hauth.time={$this->params["hauth_time"]}"; + } + + # for default HybridAuth endpoint url hauth_login_done_url + # auth.done required the IDp ID + if (!isset($this->params["login_done"]) ) { + $this->params["login_done"] = $HYBRID_AUTH_URL_BASE . ( strpos($HYBRID_AUTH_URL_BASE, '?') ? '&' : '?' ) . "hauth.done={$this->id}"; + } + + # workaround to solve windows live authentication since microsoft disallowed redirect urls to contain any parameters + # http://mywebsite.com/path_to_hybridauth/?hauth.done=Live will not work + if ($this->id=="Live") { + $this->params["login_done"] = $HYBRID_AUTH_URL_BASE."live.php"; + } + + # Workaround to fix broken callback urls for the Facebook OAuth client + if ($this->adapter->useSafeUrls) { + $this->params['login_done'] = str_replace('hauth.done', 'hauth_done', $this->params['login_done']); + } + + if (isset($this->params["hauth_return_to"])) { + Hybrid_Auth::storage()->set("hauth_session.{$this->id}.hauth_return_to", $this->params["hauth_return_to"]); + } + if (isset($this->params["login_done"])) { + Hybrid_Auth::storage()->set("hauth_session.{$this->id}.hauth_endpoint", $this->params["login_done"]); + } + Hybrid_Auth::storage()->set("hauth_session.{$this->id}.id_provider_params", $this->params); + + // store config to be used by the end point + Hybrid_Auth::storage()->config("CONFIG", Hybrid_Auth::$config); + + // move on + Hybrid_Logger::debug("Hybrid_Provider_Adapter::login( {$this->id} ), redirect the user to login_start URL."); + + // redirect + if (empty($this->params["redirect_mode"])) { + Hybrid_Auth::redirect($this->params["login_start"]); + } else { + Hybrid_Auth::redirect($this->params["login_start"],$this->params["redirect_mode"]); + } + } + + /** + * Let hybridauth forget all about the user for the current provider + * @return bool + */ + function logout() { + $this->adapter->logout(); + } + + // -------------------------------------------------------------------- + + /** + * Return true if the user is connected to the current provider + * @return bool + */ + public function isUserConnected() { + return $this->adapter->isUserConnected(); + } + + // -------------------------------------------------------------------- + + /** + * Call adapter methods defined in the adapter model: + * getUserProfile() + * getUserContacts() + * getUserActivity() + * setUserStatus() + * + * @param string $name Method name + * @param array $arguments Call arguments + * @return mixed + * @throws Exception + */ + public function __call($name, $arguments) { + Hybrid_Logger::info("Enter Hybrid_Provider_Adapter::$name(), Provider: {$this->id}"); + + if (!$this->isUserConnected()) { + throw new Exception("User not connected to the provider {$this->id}.", 7); + } + + if (!method_exists($this->adapter, $name)) { + throw new Exception("Call to undefined function Hybrid_Providers_{$this->id}::$name()."); + } + + return call_user_func_array(array($this->adapter, $name), $arguments); + } + + /** + * If the user is connected, then return the access_token and access_token_secret + * if the provider api use oauth + * + * + * array( + * 'access_token' => '', + * 'access_token_secret' => '', + * 'refresh_token' => '', + * 'expires_in' => '', + * 'expires_at' => '', + * ) + * + * @return array + */ + public function getAccessToken() { + if (!$this->adapter->isUserConnected()) { + Hybrid_Logger::error("User not connected to the provider."); + throw new Exception("User not connected to the provider.", 7); + } + + return array( + "access_token" => $this->adapter->token("access_token"), // OAuth access token + "access_token_secret" => $this->adapter->token("access_token_secret"), // OAuth access token secret + "refresh_token" => $this->adapter->token("refresh_token"), // OAuth refresh token + "expires_in" => $this->adapter->token("expires_in"), // OPTIONAL. The duration in seconds of the access token lifetime + "expires_at" => $this->adapter->token("expires_at"), // OPTIONAL. Timestamp when the access_token expire. if not provided by the social api, then it should be calculated: expires_at = now + expires_in + ); + } + + /** + * Naive getter of the current connected IDp API client + * @return stdClass + * @throws Exception + */ + function api() { + if (!$this->adapter->isUserConnected()) { + Hybrid_Logger::error("User not connected to the provider."); + + throw new Exception("User not connected to the provider.", 7); + } + return $this->adapter->api; + } + + /** + * Redirect the user to hauth_return_to (the callback url) + * @return void + */ + function returnToCallbackUrl() { + // get the stored callback url + $callback_url = Hybrid_Auth::storage()->get("hauth_session.{$this->id}.hauth_return_to"); + + // if the user presses the back button in the browser and we already deleted the hauth_return_to from + // the session in the previous request, we will redirect to '/' instead of displaying a blank page. + if (!$callback_url) { + $callback_url = '/'; + } + + // remove some unneeded stored data + Hybrid_Auth::storage()->delete("hauth_session.{$this->id}.hauth_return_to"); + Hybrid_Auth::storage()->delete("hauth_session.{$this->id}.hauth_endpoint"); + Hybrid_Auth::storage()->delete("hauth_session.{$this->id}.id_provider_params"); + + // back to home + Hybrid_Auth::redirect($callback_url); + } + + /** + * Return the provider config by id + * + * @param string $id Config key + * @return mixed + */ + function getConfigById($id) { + if (isset(Hybrid_Auth::$config["providers"][$id])) { + return Hybrid_Auth::$config["providers"][$id]; + } + return null; + } + + /** + * Return the provider config by id; case insensitive + * + * @param string $id Provider id + * @return mixed + */ + function getProviderCiId($id) { + foreach (Hybrid_Auth::$config["providers"] as $idpid => $params) { + if (strtolower($idpid) == strtolower($id)) { + return $idpid; + } + } + return null; + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Provider_Model.php b/e107_handlers/hybridauth/Hybrid/Provider_Model.php index 9f5798bcd..320cee9e1 100644 --- a/e107_handlers/hybridauth/Hybrid/Provider_Model.php +++ b/e107_handlers/hybridauth/Hybrid/Provider_Model.php @@ -1,247 +1,247 @@ -params = Hybrid_Auth::storage()->get("hauth_session.$providerId.id_provider_params"); - } else { - $this->params = $params; - } - - // idp id - $this->providerId = $providerId; - - // set HybridAuth endpoint for this provider - $this->endpoint = Hybrid_Auth::storage()->get("hauth_session.$providerId.hauth_endpoint"); - - // idp config - $this->config = $config; - - // new user instance - $this->user = new Hybrid_User(); - $this->user->providerId = $providerId; - - // initialize the current provider adapter - $this->initialize(); - - Hybrid_Logger::debug("Hybrid_Provider_Model::__construct( $providerId ) initialized. dump current adapter instance: ", serialize($this)); - } - - /** - * IDp wrappers initializer - * - * The main job of wrappers initializer is to performs (depend on the IDp api client it self): - * - include some libs needed by this provider, - * - check IDp key and secret, - * - set some needed parameters (stored in $this->params) by this IDp api client - * - create and setup an instance of the IDp api client on $this->api - * - * @return void - * @throws Exception - */ - abstract protected function initialize(); - - /** - * Begin login - * - * @return void - * @throws Exception - */ - abstract public function loginBegin(); - - /** - * Finish login - * @return void - * @throws Exception - */ - abstract public function loginFinish(); - - /** - * Generic logout, just erase current provider adapter stored data to let Hybrid_Auth all forget about it - * @return bool - */ - function logout() { - Hybrid_Logger::info("Enter [{$this->providerId}]::logout()"); - $this->clearTokens(); - return true; - } - - /** - * Grab the user profile from the IDp api client - * @return Hybrid_User_Profile - * @throws Exception - */ - function getUserProfile() { - Hybrid_Logger::error("HybridAuth do not provide users contacts list for {$this->providerId} yet."); - throw new Exception("Provider does not support this feature.", 8); - } - - /** - * Load the current logged in user contacts list from the IDp api client - * @return Hybrid_User_Contact[] - * @throws Exception - */ - function getUserContacts() { - Hybrid_Logger::error("HybridAuth do not provide users contacts list for {$this->providerId} yet."); - throw new Exception("Provider does not support this feature.", 8); - } - - /** - * Return the user activity stream - * @return Hybrid_User_Activity[] - * @throws Exception - */ - function getUserActivity($stream) { - Hybrid_Logger::error("HybridAuth do not provide user's activity stream for {$this->providerId} yet."); - throw new Exception("Provider does not support this feature.", 8); - } - - /** - * Set user status - * @return mixed Provider response - * @throws Exception - */ - function setUserStatus($status) { - Hybrid_Logger::error("HybridAuth do not provide user's activity stream for {$this->providerId} yet."); - throw new Exception("Provider does not support this feature.", 8); - } - - /** - * Return the user status - * @return mixed Provider response - * @throws Exception - */ - function getUserStatus($statusid) { - Hybrid_Logger::error("HybridAuth do not provide user's status for {$this->providerId} yet."); - throw new Exception("Provider does not support this feature.", 8); - } - - /** - * Return true if the user is connected to the current provider - * @return bool - */ - public function isUserConnected() { - return (bool) Hybrid_Auth::storage()->get("hauth_session.{$this->providerId}.is_logged_in"); - } - - /** - * Set user to connected - * @return void - */ - public function setUserConnected() { - Hybrid_Logger::info("Enter [{$this->providerId}]::setUserConnected()"); - Hybrid_Auth::storage()->set("hauth_session.{$this->providerId}.is_logged_in", 1); - } - - /** - * Set user to unconnected - * @return void - */ - public function setUserUnconnected() { - Hybrid_Logger::info("Enter [{$this->providerId}]::setUserUnconnected()"); - Hybrid_Auth::storage()->set("hauth_session.{$this->providerId}.is_logged_in", 0); - } - - /** - * Get or set a token - * @return string - */ - public function token($token, $value = null) { - if ($value === null) { - return Hybrid_Auth::storage()->get("hauth_session.{$this->providerId}.token.$token"); - } else { - Hybrid_Auth::storage()->set("hauth_session.{$this->providerId}.token.$token", $value); - } - } - - /** - * Delete a stored token - * @return void - */ - public function deleteToken($token) { - Hybrid_Auth::storage()->delete("hauth_session.{$this->providerId}.token.$token"); - } - - /** - * Clear all existent tokens for this provider - * @return void - */ - public function clearTokens() { - Hybrid_Auth::storage()->deleteMatch("hauth_session.{$this->providerId}."); - } - -} +params = Hybrid_Auth::storage()->get("hauth_session.$providerId.id_provider_params"); + } else { + $this->params = $params; + } + + // idp id + $this->providerId = $providerId; + + // set HybridAuth endpoint for this provider + $this->endpoint = Hybrid_Auth::storage()->get("hauth_session.$providerId.hauth_endpoint"); + + // idp config + $this->config = $config; + + // new user instance + $this->user = new Hybrid_User(); + $this->user->providerId = $providerId; + + // initialize the current provider adapter + $this->initialize(); + + Hybrid_Logger::debug("Hybrid_Provider_Model::__construct( $providerId ) initialized. dump current adapter instance: ", serialize($this)); + } + + /** + * IDp wrappers initializer + * + * The main job of wrappers initializer is to performs (depend on the IDp api client it self): + * - include some libs needed by this provider, + * - check IDp key and secret, + * - set some needed parameters (stored in $this->params) by this IDp api client + * - create and setup an instance of the IDp api client on $this->api + * + * @return void + * @throws Exception + */ + abstract protected function initialize(); + + /** + * Begin login + * + * @return void + * @throws Exception + */ + abstract public function loginBegin(); + + /** + * Finish login + * @return void + * @throws Exception + */ + abstract public function loginFinish(); + + /** + * Generic logout, just erase current provider adapter stored data to let Hybrid_Auth all forget about it + * @return bool + */ + function logout() { + Hybrid_Logger::info("Enter [{$this->providerId}]::logout()"); + $this->clearTokens(); + return true; + } + + /** + * Grab the user profile from the IDp api client + * @return Hybrid_User_Profile + * @throws Exception + */ + function getUserProfile() { + Hybrid_Logger::error("HybridAuth do not provide users contacts list for {$this->providerId} yet."); + throw new Exception("Provider does not support this feature.", 8); + } + + /** + * Load the current logged in user contacts list from the IDp api client + * @return Hybrid_User_Contact[] + * @throws Exception + */ + function getUserContacts() { + Hybrid_Logger::error("HybridAuth do not provide users contacts list for {$this->providerId} yet."); + throw new Exception("Provider does not support this feature.", 8); + } + + /** + * Return the user activity stream + * @return Hybrid_User_Activity[] + * @throws Exception + */ + function getUserActivity($stream) { + Hybrid_Logger::error("HybridAuth do not provide user's activity stream for {$this->providerId} yet."); + throw new Exception("Provider does not support this feature.", 8); + } + + /** + * Set user status + * @return mixed Provider response + * @throws Exception + */ + function setUserStatus($status) { + Hybrid_Logger::error("HybridAuth do not provide user's activity stream for {$this->providerId} yet."); + throw new Exception("Provider does not support this feature.", 8); + } + + /** + * Return the user status + * @return mixed Provider response + * @throws Exception + */ + function getUserStatus($statusid) { + Hybrid_Logger::error("HybridAuth do not provide user's status for {$this->providerId} yet."); + throw new Exception("Provider does not support this feature.", 8); + } + + /** + * Return true if the user is connected to the current provider + * @return bool + */ + public function isUserConnected() { + return (bool) Hybrid_Auth::storage()->get("hauth_session.{$this->providerId}.is_logged_in"); + } + + /** + * Set user to connected + * @return void + */ + public function setUserConnected() { + Hybrid_Logger::info("Enter [{$this->providerId}]::setUserConnected()"); + Hybrid_Auth::storage()->set("hauth_session.{$this->providerId}.is_logged_in", 1); + } + + /** + * Set user to unconnected + * @return void + */ + public function setUserUnconnected() { + Hybrid_Logger::info("Enter [{$this->providerId}]::setUserUnconnected()"); + Hybrid_Auth::storage()->set("hauth_session.{$this->providerId}.is_logged_in", 0); + } + + /** + * Get or set a token + * @return string + */ + public function token($token, $value = null) { + if ($value === null) { + return Hybrid_Auth::storage()->get("hauth_session.{$this->providerId}.token.$token"); + } else { + Hybrid_Auth::storage()->set("hauth_session.{$this->providerId}.token.$token", $value); + } + } + + /** + * Delete a stored token + * @return void + */ + public function deleteToken($token) { + Hybrid_Auth::storage()->delete("hauth_session.{$this->providerId}.token.$token"); + } + + /** + * Clear all existent tokens for this provider + * @return void + */ + public function clearTokens() { + Hybrid_Auth::storage()->deleteMatch("hauth_session.{$this->providerId}."); + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Provider_Model_OAuth1.php b/e107_handlers/hybridauth/Hybrid/Provider_Model_OAuth1.php index 23fd2d38d..6f5f239ae 100644 --- a/e107_handlers/hybridauth/Hybrid/Provider_Model_OAuth1.php +++ b/e107_handlers/hybridauth/Hybrid/Provider_Model_OAuth1.php @@ -1,174 +1,174 @@ - "OK: Success!", - 304 => "Not Modified: There was no new data to return.", - 400 => "Bad Request: The request was invalid.", - 401 => "Unauthorized.", - 403 => "Forbidden: The request is understood, but it has been refused.", - 404 => "Not Found: The URI requested is invalid or the resource requested does not exists.", - 406 => "Not Acceptable.", - 500 => "Internal Server Error: Something is broken.", - 502 => "Bad Gateway.", - 503 => "Service Unavailable." - ); - - if (!$code && $this->api) { - $code = $this->api->http_code; - } - - if (isset($http_status_codes[$code])) { - return $code . " " . $http_status_codes[$code]; - } - } - - /** - * {@inheritdoc} - */ - function initialize() { - // 1 - check application credentials - if (!$this->config["keys"]["key"] || !$this->config["keys"]["secret"]) { - throw new Exception("Your application key and secret are required in order to connect to {$this->providerId}.", 4); - } - - // 2 - include OAuth lib and client - if (! class_exists('OAuthConsumer') ) { - require_once Hybrid_Auth::$config["path_libraries"] . "OAuth/OAuth.php"; - } - require_once Hybrid_Auth::$config["path_libraries"] . "OAuth/OAuth1Client.php"; - - // 3.1 - setup access_token if any stored - if ($this->token("access_token")) { - $this->api = new OAuth1Client( - $this->config["keys"]["key"], $this->config["keys"]["secret"], $this->token("access_token"), $this->token("access_token_secret") - ); - } - - // 3.2 - setup request_token if any stored, in order to exchange with an access token - elseif ($this->token("request_token")) { - $this->api = new OAuth1Client( - $this->config["keys"]["key"], $this->config["keys"]["secret"], $this->token("request_token"), $this->token("request_token_secret") - ); - } - - // 3.3 - instanciate OAuth client with client credentials - else { - $this->api = new OAuth1Client($this->config["keys"]["key"], $this->config["keys"]["secret"]); - } - - // Set curl proxy if exist - if (isset(Hybrid_Auth::$config["proxy"])) { - $this->api->curl_proxy = Hybrid_Auth::$config["proxy"]; - } - } - - /** - * {@inheritdoc} - */ - function loginBegin() { - $tokens = $this->api->requestToken($this->endpoint); - - // request tokens as received from provider - $this->request_tokens_raw = $tokens; - - // check the last HTTP status code returned - if ($this->api->http_code != 200) { - throw new Exception("Authentication failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code), 5); - } - - if (!isset($tokens["oauth_token"])) { - throw new Exception("Authentication failed! {$this->providerId} returned an invalid oauth token.", 5); - } - - $this->token("request_token", $tokens["oauth_token"]); - $this->token("request_token_secret", $tokens["oauth_token_secret"]); - - # redirect the user to the provider authentication url - Hybrid_Auth::redirect($this->api->authorizeUrl($tokens)); - } - - /** - * {@inheritdoc} - */ - function loginFinish() { - $oauth_token = (array_key_exists('oauth_token', $_REQUEST)) ? $_REQUEST['oauth_token'] : ""; - $oauth_verifier = (array_key_exists('oauth_verifier', $_REQUEST)) ? $_REQUEST['oauth_verifier'] : ""; - - if (!$oauth_token || !$oauth_verifier) { - throw new Exception("Authentication failed! {$this->providerId} returned an invalid oauth verifier.", 5); - } - - // request an access token - $tokens = $this->api->accessToken($oauth_verifier); - - // access tokens as received from provider - $this->access_tokens_raw = $tokens; - - // check the last HTTP status code returned - if ($this->api->http_code != 200) { - throw new Exception("Authentication failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code), 5); - } - - // we should have an access_token, or else, something has gone wrong - if (!isset($tokens["oauth_token"])) { - throw new Exception("Authentication failed! {$this->providerId} returned an invalid access token.", 5); - } - - // we no more need to store request tokens - $this->deleteToken("request_token"); - $this->deleteToken("request_token_secret"); - - // store access_token for later user - $this->token("access_token", $tokens['oauth_token']); - $this->token("access_token_secret", $tokens['oauth_token_secret']); - - // set user as logged in to the current provider - $this->setUserConnected(); - } - -} + "OK: Success!", + 304 => "Not Modified: There was no new data to return.", + 400 => "Bad Request: The request was invalid.", + 401 => "Unauthorized.", + 403 => "Forbidden: The request is understood, but it has been refused.", + 404 => "Not Found: The URI requested is invalid or the resource requested does not exists.", + 406 => "Not Acceptable.", + 500 => "Internal Server Error: Something is broken.", + 502 => "Bad Gateway.", + 503 => "Service Unavailable." + ); + + if (!$code && $this->api) { + $code = $this->api->http_code; + } + + if (isset($http_status_codes[$code])) { + return $code . " " . $http_status_codes[$code]; + } + } + + /** + * {@inheritdoc} + */ + function initialize() { + // 1 - check application credentials + if (!$this->config["keys"]["key"] || !$this->config["keys"]["secret"]) { + throw new Exception("Your application key and secret are required in order to connect to {$this->providerId}.", 4); + } + + // 2 - include OAuth lib and client + if (! class_exists('OAuthConsumer') ) { + require_once Hybrid_Auth::$config["path_libraries"] . "OAuth/OAuth.php"; + } + require_once Hybrid_Auth::$config["path_libraries"] . "OAuth/OAuth1Client.php"; + + // 3.1 - setup access_token if any stored + if ($this->token("access_token")) { + $this->api = new OAuth1Client( + $this->config["keys"]["key"], $this->config["keys"]["secret"], $this->token("access_token"), $this->token("access_token_secret") + ); + } + + // 3.2 - setup request_token if any stored, in order to exchange with an access token + elseif ($this->token("request_token")) { + $this->api = new OAuth1Client( + $this->config["keys"]["key"], $this->config["keys"]["secret"], $this->token("request_token"), $this->token("request_token_secret") + ); + } + + // 3.3 - instanciate OAuth client with client credentials + else { + $this->api = new OAuth1Client($this->config["keys"]["key"], $this->config["keys"]["secret"]); + } + + // Set curl proxy if exist + if (isset(Hybrid_Auth::$config["proxy"])) { + $this->api->curl_proxy = Hybrid_Auth::$config["proxy"]; + } + } + + /** + * {@inheritdoc} + */ + function loginBegin() { + $tokens = $this->api->requestToken($this->endpoint); + + // request tokens as received from provider + $this->request_tokens_raw = $tokens; + + // check the last HTTP status code returned + if ($this->api->http_code != 200) { + throw new Exception("Authentication failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code), 5); + } + + if (!isset($tokens["oauth_token"])) { + throw new Exception("Authentication failed! {$this->providerId} returned an invalid oauth token.", 5); + } + + $this->token("request_token", $tokens["oauth_token"]); + $this->token("request_token_secret", $tokens["oauth_token_secret"]); + + # redirect the user to the provider authentication url + Hybrid_Auth::redirect($this->api->authorizeUrl($tokens)); + } + + /** + * {@inheritdoc} + */ + function loginFinish() { + $oauth_token = (array_key_exists('oauth_token', $_REQUEST)) ? $_REQUEST['oauth_token'] : ""; + $oauth_verifier = (array_key_exists('oauth_verifier', $_REQUEST)) ? $_REQUEST['oauth_verifier'] : ""; + + if (!$oauth_token || !$oauth_verifier) { + throw new Exception("Authentication failed! {$this->providerId} returned an invalid oauth verifier.", 5); + } + + // request an access token + $tokens = $this->api->accessToken($oauth_verifier); + + // access tokens as received from provider + $this->access_tokens_raw = $tokens; + + // check the last HTTP status code returned + if ($this->api->http_code != 200) { + throw new Exception("Authentication failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code), 5); + } + + // we should have an access_token, or else, something has gone wrong + if (!isset($tokens["oauth_token"])) { + throw new Exception("Authentication failed! {$this->providerId} returned an invalid access token.", 5); + } + + // we no more need to store request tokens + $this->deleteToken("request_token"); + $this->deleteToken("request_token_secret"); + + // store access_token for later user + $this->token("access_token", $tokens['oauth_token']); + $this->token("access_token_secret", $tokens['oauth_token_secret']); + + // set user as logged in to the current provider + $this->setUserConnected(); + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Provider_Model_OAuth2.php b/e107_handlers/hybridauth/Hybrid/Provider_Model_OAuth2.php index b9de4e2bc..17a2103bd 100644 --- a/e107_handlers/hybridauth/Hybrid/Provider_Model_OAuth2.php +++ b/e107_handlers/hybridauth/Hybrid/Provider_Model_OAuth2.php @@ -1,184 +1,184 @@ - "OK: Success!", - 304 => "Not Modified: There was no new data to return.", - 400 => "Bad Request: The request was invalid.", - 401 => "Unauthorized.", - 403 => "Forbidden: The request is understood, but it has been refused.", - 404 => "Not Found: The URI requested is invalid or the resource requested does not exists.", - 406 => "Not Acceptable.", - 500 => "Internal Server Error: Something is broken.", - 502 => "Bad Gateway.", - 503 => "Service Unavailable." - ); - - if (!$code && $this->api) { - $code = $this->api->http_code; - } - - if (isset($http_status_codes[$code])) { - return $code . " " . $http_status_codes[$code]; - } - } - - /** - * Adapter initializer - */ - function initialize() { - if (!$this->config["keys"]["id"] || !$this->config["keys"]["secret"]) { - throw new Exception("Your application id and secret are required in order to connect to {$this->providerId}.", 4); - } - - // override requested scope - if (isset($this->config["scope"]) && !empty($this->config["scope"])) { - $this->scope = $this->config["scope"]; - } - - // include OAuth2 client - require_once Hybrid_Auth::$config["path_libraries"] . "OAuth/OAuth2Client.php"; - - // create a new OAuth2 client instance - $this->api = new OAuth2Client($this->config["keys"]["id"], $this->config["keys"]["secret"], $this->endpoint, $this->compressed); - - // If we have an access token, set it - if ($this->token("access_token")) { - $this->api->access_token = $this->token("access_token"); - $this->api->refresh_token = $this->token("refresh_token"); - $this->api->access_token_expires_in = $this->token("expires_in"); - $this->api->access_token_expires_at = $this->token("expires_at"); - } - - // Set curl proxy if exist - if (isset(Hybrid_Auth::$config["proxy"])) { - $this->api->curl_proxy = Hybrid_Auth::$config["proxy"]; - } - } - - /** - * {@inheritdoc} - */ - function loginBegin() { - // redirect the user to the provider authentication url - Hybrid_Auth::redirect($this->api->authorizeUrl(array("scope" => $this->scope))); - } - - /** - * {@inheritdoc} - */ - function loginFinish() { - $error = (array_key_exists('error', $_REQUEST)) ? $_REQUEST['error'] : ""; - - // check for errors - if ($error) { - throw new Exception("Authentication failed! {$this->providerId} returned an error: $error", 5); - } - - // try to authenticate user - $code = (array_key_exists('code', $_REQUEST)) ? $_REQUEST['code'] : ""; - - try { - $this->api->authenticate($code); - } catch (Exception $e) { - throw new Exception("User profile request failed! {$this->providerId} returned an error: " . $e->getMessage(), 6); - } - - // check if authenticated - if (!$this->api->access_token) { - throw new Exception("Authentication failed! {$this->providerId} returned an invalid access token.", 5); - } - - // store tokens - $this->token("access_token", $this->api->access_token); - $this->token("refresh_token", $this->api->refresh_token); - $this->token("expires_in", $this->api->access_token_expires_in); - $this->token("expires_at", $this->api->access_token_expires_at); - - // set user connected locally - $this->setUserConnected(); - } - - /** - * {@inheritdoc} - */ - function refreshToken() { - // have an access token? - if ($this->api->access_token) { - - // have to refresh? - if ($this->api->refresh_token && $this->api->access_token_expires_at) { - - // expired? - if ($this->api->access_token_expires_at <= time()) { - $response = $this->api->refreshToken(array("refresh_token" => $this->api->refresh_token)); - - if (!isset($response->access_token) || !$response->access_token) { - // set the user as disconnected at this point and throw an exception - $this->setUserUnconnected(); - - throw new Exception("The Authorization Service has return an invalid response while requesting a new access token. " . (string) $response->error); - } - - // set new access_token - $this->api->access_token = $response->access_token; - - if (isset($response->refresh_token)) - $this->api->refresh_token = $response->refresh_token; - - if (isset($response->expires_in)) { - $this->api->access_token_expires_in = $response->expires_in; - - // even given by some idp, we should calculate this - $this->api->access_token_expires_at = time() + $response->expires_in; - } - } - } - - // re store tokens - $this->token("access_token", $this->api->access_token); - $this->token("refresh_token", $this->api->refresh_token); - $this->token("expires_in", $this->api->access_token_expires_in); - $this->token("expires_at", $this->api->access_token_expires_at); - } - } - -} + "OK: Success!", + 304 => "Not Modified: There was no new data to return.", + 400 => "Bad Request: The request was invalid.", + 401 => "Unauthorized.", + 403 => "Forbidden: The request is understood, but it has been refused.", + 404 => "Not Found: The URI requested is invalid or the resource requested does not exists.", + 406 => "Not Acceptable.", + 500 => "Internal Server Error: Something is broken.", + 502 => "Bad Gateway.", + 503 => "Service Unavailable." + ); + + if (!$code && $this->api) { + $code = $this->api->http_code; + } + + if (isset($http_status_codes[$code])) { + return $code . " " . $http_status_codes[$code]; + } + } + + /** + * Adapter initializer + */ + function initialize() { + if (!$this->config["keys"]["id"] || !$this->config["keys"]["secret"]) { + throw new Exception("Your application id and secret are required in order to connect to {$this->providerId}.", 4); + } + + // override requested scope + if (isset($this->config["scope"]) && !empty($this->config["scope"])) { + $this->scope = $this->config["scope"]; + } + + // include OAuth2 client + require_once Hybrid_Auth::$config["path_libraries"] . "OAuth/OAuth2Client.php"; + + // create a new OAuth2 client instance + $this->api = new OAuth2Client($this->config["keys"]["id"], $this->config["keys"]["secret"], $this->endpoint, $this->compressed); + + // If we have an access token, set it + if ($this->token("access_token")) { + $this->api->access_token = $this->token("access_token"); + $this->api->refresh_token = $this->token("refresh_token"); + $this->api->access_token_expires_in = $this->token("expires_in"); + $this->api->access_token_expires_at = $this->token("expires_at"); + } + + // Set curl proxy if exist + if (isset(Hybrid_Auth::$config["proxy"])) { + $this->api->curl_proxy = Hybrid_Auth::$config["proxy"]; + } + } + + /** + * {@inheritdoc} + */ + function loginBegin() { + // redirect the user to the provider authentication url + Hybrid_Auth::redirect($this->api->authorizeUrl(array("scope" => $this->scope))); + } + + /** + * {@inheritdoc} + */ + function loginFinish() { + $error = (array_key_exists('error', $_REQUEST)) ? $_REQUEST['error'] : ""; + + // check for errors + if ($error) { + throw new Exception("Authentication failed! {$this->providerId} returned an error: $error", 5); + } + + // try to authenticate user + $code = (array_key_exists('code', $_REQUEST)) ? $_REQUEST['code'] : ""; + + try { + $this->api->authenticate($code); + } catch (Exception $e) { + throw new Exception("User profile request failed! {$this->providerId} returned an error: " . $e->getMessage(), 6); + } + + // check if authenticated + if (!$this->api->access_token) { + throw new Exception("Authentication failed! {$this->providerId} returned an invalid access token.", 5); + } + + // store tokens + $this->token("access_token", $this->api->access_token); + $this->token("refresh_token", $this->api->refresh_token); + $this->token("expires_in", $this->api->access_token_expires_in); + $this->token("expires_at", $this->api->access_token_expires_at); + + // set user connected locally + $this->setUserConnected(); + } + + /** + * {@inheritdoc} + */ + function refreshToken() { + // have an access token? + if ($this->api->access_token) { + + // have to refresh? + if ($this->api->refresh_token && $this->api->access_token_expires_at) { + + // expired? + if ($this->api->access_token_expires_at <= time()) { + $response = $this->api->refreshToken(array("refresh_token" => $this->api->refresh_token)); + + if (!isset($response->access_token) || !$response->access_token) { + // set the user as disconnected at this point and throw an exception + $this->setUserUnconnected(); + + throw new Exception("The Authorization Service has return an invalid response while requesting a new access token. " . (string) $response->error); + } + + // set new access_token + $this->api->access_token = $response->access_token; + + if (isset($response->refresh_token)) + $this->api->refresh_token = $response->refresh_token; + + if (isset($response->expires_in)) { + $this->api->access_token_expires_in = $response->expires_in; + + // even given by some idp, we should calculate this + $this->api->access_token_expires_at = time() + $response->expires_in; + } + } + } + + // re store tokens + $this->token("access_token", $this->api->access_token); + $this->token("refresh_token", $this->api->refresh_token); + $this->token("expires_in", $this->api->access_token_expires_in); + $this->token("expires_at", $this->api->access_token_expires_at); + } + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Provider_Model_OpenID.php b/e107_handlers/hybridauth/Hybrid/Provider_Model_OpenID.php index 08fa36cad..d3ec7cab5 100644 --- a/e107_handlers/hybridauth/Hybrid/Provider_Model_OpenID.php +++ b/e107_handlers/hybridauth/Hybrid/Provider_Model_OpenID.php @@ -1,170 +1,170 @@ -public $openidIdentifier = ""; - * - * Hybrid_Provider_Model_OpenID use LightOpenID lib which can be found on - * Hybrid/thirdparty/OpenID/LightOpenID.php - */ -class Hybrid_Provider_Model_OpenID extends Hybrid_Provider_Model { - - /** - * Provider API client - * @var LightOpenID - */ - public $api = null; - - /** - * Openid provider identifier - * @var string - */ - public $openidIdentifier = ""; - - /** - * {@inheritdoc} - */ - function initialize() { - if (isset($this->params["openid_identifier"])) { - $this->openidIdentifier = $this->params["openid_identifier"]; - } - - // include LightOpenID lib - require_once Hybrid_Auth::$config["path_libraries"] . "OpenID/LightOpenID.php"; - - // An error was occurring when proxy wasn't set. Not sure where proxy was meant to be set/initialized. - Hybrid_Auth::$config['proxy'] = isset(Hybrid_Auth::$config['proxy']) ? Hybrid_Auth::$config['proxy'] : ''; - - $hostPort = parse_url(Hybrid_Auth::$config["base_url"], PHP_URL_PORT); - $hostUrl = parse_url(Hybrid_Auth::$config["base_url"], PHP_URL_HOST); - - // Check for port on url - if ($hostPort) { - $hostUrl .= ':' . $hostPort; - } - - $this->api = new LightOpenID($hostUrl, Hybrid_Auth::$config["proxy"]); - } - - /** - * {@inheritdoc} - */ - function loginBegin() { - if (empty($this->openidIdentifier)) { - throw new Exception("OpenID adapter require the identity provider identifier 'openid_identifier' as an extra parameter.", 4); - } - - $this->api->identity = $this->openidIdentifier; - $this->api->returnUrl = $this->endpoint; - $this->api->required = array( - 'namePerson/first', - 'namePerson/last', - 'namePerson/friendly', - 'namePerson', - 'contact/email', - 'birthDate', - 'birthDate/birthDay', - 'birthDate/birthMonth', - 'birthDate/birthYear', - 'person/gender', - 'pref/language', - 'contact/postalCode/home', - 'contact/city/home', - 'contact/country/home', - 'media/image/default', - ); - - # redirect the user to the provider authentication url - Hybrid_Auth::redirect($this->api->authUrl()); - } - - /** - * {@inheritdoc} - */ - function loginFinish() { - # if user don't grant access of their data to your site, halt with an Exception - if ($this->api->mode == 'cancel') { - throw new Exception("Authentication failed! User has canceled authentication!", 5); - } - - # if something goes wrong - if (!$this->api->validate()) { - throw new Exception("Authentication failed. Invalid request received!", 5); - } - - # fetch received user data - $response = $this->api->getAttributes(); - - # store the user profile - $this->user->profile->identifier = $this->api->identity; - - $this->user->profile->firstName = (array_key_exists("namePerson/first", $response)) ? $response["namePerson/first"] : ""; - $this->user->profile->lastName = (array_key_exists("namePerson/last", $response)) ? $response["namePerson/last"] : ""; - $this->user->profile->displayName = (array_key_exists("namePerson", $response)) ? $response["namePerson"] : ""; - $this->user->profile->email = (array_key_exists("contact/email", $response)) ? $response["contact/email"] : ""; - $this->user->profile->language = (array_key_exists("pref/language", $response)) ? $response["pref/language"] : ""; - $this->user->profile->country = (array_key_exists("contact/country/home", $response)) ? $response["contact/country/home"] : ""; - $this->user->profile->zip = (array_key_exists("contact/postalCode/home", $response)) ? $response["contact/postalCode/home"] : ""; - $this->user->profile->gender = (array_key_exists("person/gender", $response)) ? $response["person/gender"] : ""; - $this->user->profile->photoURL = (array_key_exists("media/image/default", $response)) ? $response["media/image/default"] : ""; - - $this->user->profile->birthDay = (array_key_exists("birthDate/birthDay", $response)) ? $response["birthDate/birthDay"] : ""; - $this->user->profile->birthMonth = (array_key_exists("birthDate/birthMonth", $response)) ? $response["birthDate/birthMonth"] : ""; - $this->user->profile->birthYear = (array_key_exists("birthDate/birthDate", $response)) ? $response["birthDate/birthDate"] : ""; - - if (isset($response['namePerson/friendly']) && !empty($response['namePerson/friendly']) && !$this->user->profile->displayName) { - $this->user->profile->displayName = $response["namePerson/friendly"]; - } - - if (isset($response['birthDate']) && !empty($response['birthDate']) && !$this->user->profile->birthDay) { - list( $birthday_year, $birthday_month, $birthday_day ) = $response['birthDate']; - - $this->user->profile->birthDay = (int) $birthday_day; - $this->user->profile->birthMonth = (int) $birthday_month; - $this->user->profile->birthYear = (int) $birthday_year; - } - - if (!$this->user->profile->displayName) { - $this->user->profile->displayName = trim($this->user->profile->firstName . " " . $this->user->profile->lastName); - } - - if ($this->user->profile->gender == "f") { - $this->user->profile->gender = "female"; - } - - if ($this->user->profile->gender == "m") { - $this->user->profile->gender = "male"; - } - - // set user as logged in - $this->setUserConnected(); - - // with openid providers we get the user profile only once, so store it - Hybrid_Auth::storage()->set("hauth_session.{$this->providerId}.user", $this->user); - } - - /** - * {@inheritdoc} - */ - function getUserProfile() { - // try to get the user profile from stored data - $this->user = Hybrid_Auth::storage()->get("hauth_session.{$this->providerId}.user"); - - // if not found - if (!is_object($this->user)) { - throw new Exception("User profile request failed! User is not connected to {$this->providerId} or his session has expired.", 6); - } - - return $this->user->profile; - } - -} +public $openidIdentifier = ""; + * + * Hybrid_Provider_Model_OpenID use LightOpenID lib which can be found on + * Hybrid/thirdparty/OpenID/LightOpenID.php + */ +class Hybrid_Provider_Model_OpenID extends Hybrid_Provider_Model { + + /** + * Provider API client + * @var LightOpenID + */ + public $api = null; + + /** + * Openid provider identifier + * @var string + */ + public $openidIdentifier = ""; + + /** + * {@inheritdoc} + */ + function initialize() { + if (isset($this->params["openid_identifier"])) { + $this->openidIdentifier = $this->params["openid_identifier"]; + } + + // include LightOpenID lib + require_once Hybrid_Auth::$config["path_libraries"] . "OpenID/LightOpenID.php"; + + // An error was occurring when proxy wasn't set. Not sure where proxy was meant to be set/initialized. + Hybrid_Auth::$config['proxy'] = isset(Hybrid_Auth::$config['proxy']) ? Hybrid_Auth::$config['proxy'] : ''; + + $hostPort = parse_url(Hybrid_Auth::$config["base_url"], PHP_URL_PORT); + $hostUrl = parse_url(Hybrid_Auth::$config["base_url"], PHP_URL_HOST); + + // Check for port on url + if ($hostPort) { + $hostUrl .= ':' . $hostPort; + } + + $this->api = new LightOpenID($hostUrl, Hybrid_Auth::$config["proxy"]); + } + + /** + * {@inheritdoc} + */ + function loginBegin() { + if (empty($this->openidIdentifier)) { + throw new Exception("OpenID adapter require the identity provider identifier 'openid_identifier' as an extra parameter.", 4); + } + + $this->api->identity = $this->openidIdentifier; + $this->api->returnUrl = $this->endpoint; + $this->api->required = array( + 'namePerson/first', + 'namePerson/last', + 'namePerson/friendly', + 'namePerson', + 'contact/email', + 'birthDate', + 'birthDate/birthDay', + 'birthDate/birthMonth', + 'birthDate/birthYear', + 'person/gender', + 'pref/language', + 'contact/postalCode/home', + 'contact/city/home', + 'contact/country/home', + 'media/image/default', + ); + + # redirect the user to the provider authentication url + Hybrid_Auth::redirect($this->api->authUrl()); + } + + /** + * {@inheritdoc} + */ + function loginFinish() { + # if user don't grant access of their data to your site, halt with an Exception + if ($this->api->mode == 'cancel') { + throw new Exception("Authentication failed! User has canceled authentication!", 5); + } + + # if something goes wrong + if (!$this->api->validate()) { + throw new Exception("Authentication failed. Invalid request received!", 5); + } + + # fetch received user data + $response = $this->api->getAttributes(); + + # store the user profile + $this->user->profile->identifier = $this->api->identity; + + $this->user->profile->firstName = (array_key_exists("namePerson/first", $response)) ? $response["namePerson/first"] : ""; + $this->user->profile->lastName = (array_key_exists("namePerson/last", $response)) ? $response["namePerson/last"] : ""; + $this->user->profile->displayName = (array_key_exists("namePerson", $response)) ? $response["namePerson"] : ""; + $this->user->profile->email = (array_key_exists("contact/email", $response)) ? $response["contact/email"] : ""; + $this->user->profile->language = (array_key_exists("pref/language", $response)) ? $response["pref/language"] : ""; + $this->user->profile->country = (array_key_exists("contact/country/home", $response)) ? $response["contact/country/home"] : ""; + $this->user->profile->zip = (array_key_exists("contact/postalCode/home", $response)) ? $response["contact/postalCode/home"] : ""; + $this->user->profile->gender = (array_key_exists("person/gender", $response)) ? $response["person/gender"] : ""; + $this->user->profile->photoURL = (array_key_exists("media/image/default", $response)) ? $response["media/image/default"] : ""; + + $this->user->profile->birthDay = (array_key_exists("birthDate/birthDay", $response)) ? $response["birthDate/birthDay"] : ""; + $this->user->profile->birthMonth = (array_key_exists("birthDate/birthMonth", $response)) ? $response["birthDate/birthMonth"] : ""; + $this->user->profile->birthYear = (array_key_exists("birthDate/birthDate", $response)) ? $response["birthDate/birthDate"] : ""; + + if (isset($response['namePerson/friendly']) && !empty($response['namePerson/friendly']) && !$this->user->profile->displayName) { + $this->user->profile->displayName = $response["namePerson/friendly"]; + } + + if (isset($response['birthDate']) && !empty($response['birthDate']) && !$this->user->profile->birthDay) { + list( $birthday_year, $birthday_month, $birthday_day ) = $response['birthDate']; + + $this->user->profile->birthDay = (int) $birthday_day; + $this->user->profile->birthMonth = (int) $birthday_month; + $this->user->profile->birthYear = (int) $birthday_year; + } + + if (!$this->user->profile->displayName) { + $this->user->profile->displayName = trim($this->user->profile->firstName . " " . $this->user->profile->lastName); + } + + if ($this->user->profile->gender == "f") { + $this->user->profile->gender = "female"; + } + + if ($this->user->profile->gender == "m") { + $this->user->profile->gender = "male"; + } + + // set user as logged in + $this->setUserConnected(); + + // with openid providers we get the user profile only once, so store it + Hybrid_Auth::storage()->set("hauth_session.{$this->providerId}.user", $this->user); + } + + /** + * {@inheritdoc} + */ + function getUserProfile() { + // try to get the user profile from stored data + $this->user = Hybrid_Auth::storage()->get("hauth_session.{$this->providerId}.user"); + + // if not found + if (!is_object($this->user)) { + throw new Exception("User profile request failed! User is not connected to {$this->providerId} or his session has expired.", 6); + } + + return $this->user->profile; + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Providers/AOL.php b/e107_handlers/hybridauth/Hybrid/Providers/AOL.php index 19028c09a..d2aa66730 100644 --- a/e107_handlers/hybridauth/Hybrid/Providers/AOL.php +++ b/e107_handlers/hybridauth/Hybrid/Providers/AOL.php @@ -1,18 +1,18 @@ -config["keys"]["id"] || !$this->config["keys"]["secret"]) { - throw new Exception("Your application id and secret are required in order to connect to {$this->providerId}.", 4); - } - - if (isset($this->config['scope'])) { - $scope = $this->config['scope']; - if (is_string($scope)) { - $scope = explode(",", $scope); - } - $scope = array_map('trim', $scope); - $this->scope = $scope; - } - - $trustForwarded = isset($this->config['trustForwarded']) ? (bool)$this->config['trustForwarded'] : false; - - // Check if there is Graph SDK in thirdparty/Facebook. - if (file_exists(Hybrid_Auth::$config["path_libraries"] . "Facebook/autoload.php")) { - require_once Hybrid_Auth::$config["path_libraries"] . "Facebook/autoload.php"; - } - else { - // If Composer install was executed, try to find autoload.php. - $vendorDir = dirname(Hybrid_Auth::$config['path_base']); - do { - if (file_exists($vendorDir . "/vendor/autoload.php")) { - require_once $vendorDir . "/vendor/autoload.php"; - break; - } - } while (($vendorDir = dirname($vendorDir)) !== '/'); - } - - $this->api = new FacebookSDK([ - 'app_id' => $this->config["keys"]["id"], - 'app_secret' => $this->config["keys"]["secret"], - 'default_graph_version' => 'v2.8', - 'trustForwarded' => $trustForwarded, - ]); - } - - /** - * {@inheritdoc} - */ - function loginBegin() { - - $this->endpoint = $this->params['login_done']; - $helper = $this->api->getRedirectLoginHelper(); - - // Use re-request, because this will trigger permissions window if not all permissions are granted. - $url = $helper->getReRequestUrl($this->endpoint, $this->scope); - - // Redirect to Facebook - Hybrid_Auth::redirect($url); - } - - /** - * {@inheritdoc} - */ - function loginFinish() { - - $helper = $this->api->getRedirectLoginHelper(); - try { - $accessToken = $helper->getAccessToken($this->params['login_done']); - } catch (Facebook\Exceptions\FacebookResponseException $e) { - throw new Hybrid_Exception('Facebook Graph returned an error: ' . $e->getMessage()); - } catch (Facebook\Exceptions\FacebookSDKException $e) { - throw new Hybrid_Exception('Facebook SDK returned an error: ' . $e->getMessage()); - } - - if (!isset($accessToken)) { - if ($helper->getError()) { - throw new Hybrid_Exception(sprintf("Could not authorize user, reason: %s (%d)", $helper->getErrorDescription(), $helper->getErrorCode())); - } else { - throw new Hybrid_Exception("Could not authorize user. Bad request"); - } - } - - try { - // Validate token - $oAuth2Client = $this->api->getOAuth2Client(); - $tokenMetadata = $oAuth2Client->debugToken($accessToken); - $tokenMetadata->validateAppId($this->config["keys"]["id"]); - $tokenMetadata->validateExpiration(); - - // Exchanges a short-lived access token for a long-lived one - if (!$accessToken->isLongLived()) { - $accessToken = $oAuth2Client->getLongLivedAccessToken($accessToken); - } - } catch (FacebookSDKException $e) { - throw new Hybrid_Exception($e->getMessage(), 0, $e); - } - - $this->setUserConnected(); - $this->token("access_token", $accessToken->getValue()); - } - - /** - * {@inheritdoc} - */ - function logout() { - parent::logout(); - } - - /** - * Update user status - * - * @param mixed $status An array describing the status, or string - * @param string $pageid (optional) User page id - * @return array - * @throw Exception - */ - function setUserStatus($status, $pageid = null) { - - if (!is_array($status)) { - $status = array('message' => $status); - } - - $access_token = null; - - if (is_null($pageid)) { - $pageid = 'me'; - $access_token = $this->token('access_token'); - - // if post on page, get access_token page - } else { - - foreach ($this->getUserPages(true) as $p) { - if (isset($p['id']) && intval($p['id']) == intval($pageid)) { - $access_token = $p['access_token']; - break; - } - } - - if (is_null($access_token)) { - throw new Exception("Update user page failed, page not found or not writable!"); - } - } - - try { - $response = $this->api->post('/' . $pageid . '/feed', $status, $access_token); - } catch (FacebookSDKException $e) { - throw new Exception("Update user status failed! {$this->providerId} returned an error {$e->getMessage()}", 0, $e); - } - - return $response; - } - - /** - * {@inheridoc} - */ - function getUserPages($writableonly = false) { - if (( isset($this->config['scope']) && strpos($this->config['scope'], 'manage_pages') === false ) || (!isset($this->config['scope']) && strpos($this->scope, 'manage_pages') === false )) - throw new Exception("User status requires manage_page permission!"); - - try { - $pages = $this->api->get("/me/accounts", $this->token('access_token')); - $pages = $pages->getDecodedBody(); - } catch (FacebookApiException $e) { - throw new Exception("Cannot retrieve user pages! {$this->providerId} returned an error: {$e->getMessage()}", 0, $e); - } - - if (!isset($pages['data'])) { - return array(); - } - - if (!$writableonly) { - return $pages['data']; - } - - $wrpages = array(); - foreach ($pages['data'] as $p) { - if (isset($p['perms']) && in_array('CREATE_CONTENT', $p['perms'])) { - $wrpages[] = $p; - } - } - - return $wrpages; - } - - /** - * {@inheritdoc} - */ - function getUserProfile() { - try { - $fields = [ - 'id', - 'name', - 'first_name', - 'last_name', - 'link', - 'website', - 'gender', - 'locale', - 'about', - 'email', - 'hometown', - 'location', - 'birthday' - ]; - $response = $this->api->get('/me?fields=' . implode(',', $fields), $this->token('access_token')); - $data = $response->getDecodedBody(); - } catch (FacebookSDKException $e) { - throw new Exception("User profile request failed! {$this->providerId} returned an error: {$e->getMessage()}", 6, $e); - } - - // Store the user profile. - $this->user->profile->identifier = (array_key_exists('id', $data)) ? $data['id'] : ""; - $this->user->profile->displayName = (array_key_exists('name', $data)) ? $data['name'] : ""; - $this->user->profile->firstName = (array_key_exists('first_name', $data)) ? $data['first_name'] : ""; - $this->user->profile->lastName = (array_key_exists('last_name', $data)) ? $data['last_name'] : ""; - $this->user->profile->photoURL = $this->getUserPhoto($this->user->profile->identifier); - $this->user->profile->profileURL = (array_key_exists('link', $data)) ? $data['link'] : ""; - $this->user->profile->webSiteURL = (array_key_exists('website', $data)) ? $data['website'] : ""; - $this->user->profile->gender = (array_key_exists('gender', $data)) ? $data['gender'] : ""; - $this->user->profile->language = (array_key_exists('locale', $data)) ? $data['locale'] : ""; - $this->user->profile->description = (array_key_exists('about', $data)) ? $data['about'] : ""; - $this->user->profile->email = (array_key_exists('email', $data)) ? $data['email'] : ""; - $this->user->profile->emailVerified = (array_key_exists('email', $data)) ? $data['email'] : ""; - $this->user->profile->region = (array_key_exists("location", $data) && array_key_exists("name", $data['location'])) ? $data['location']["name"] : ""; - - if (!empty($this->user->profile->region)) { - $regionArr = explode(',', $this->user->profile->region); - if (count($regionArr) > 1) { - $this->user->profile->city = trim($regionArr[0]); - $this->user->profile->country = trim(end($regionArr)); - } - } - - if (array_key_exists('birthday', $data)) { - $birtydayPieces = explode('/', $data['birthday']); - - if (count($birtydayPieces) == 1) { - $this->user->profile->birthYear = (int)$birtydayPieces[0]; - } elseif (count($birtydayPieces) == 2) { - $this->user->profile->birthMonth = (int)$birtydayPieces[0]; - $this->user->profile->birthDay = (int)$birtydayPieces[1]; - } elseif (count($birtydayPieces) == 3) { - $this->user->profile->birthMonth = (int)$birtydayPieces[0]; - $this->user->profile->birthDay = (int)$birtydayPieces[1]; - $this->user->profile->birthYear = (int)$birtydayPieces[2]; - } - } - - return $this->user->profile; - } - - /** - * Since the Graph API 2.0, the /friends endpoint only returns friend that also use your Facebook app. - * {@inheritdoc} - */ - function getUserContacts() { - $apiCall = '?fields=link,name'; - $returnedContacts = []; - $pagedList = true; - - while ($pagedList) { - try { - $response = $this->api->get('/me/friends' . $apiCall, $this->token('access_token')); - $response = $response->getDecodedBody(); - } catch (FacebookSDKException $e) { - throw new Hybrid_Exception("User contacts request failed! {$this->providerId} returned an error {$e->getMessage()}", 0, $e); - } - - // Prepare the next call if paging links have been returned - if (array_key_exists('paging', $response) && array_key_exists('next', $response['paging'])) { - $pagedList = true; - $next_page = explode('friends', $response['paging']['next']); - $apiCall = $next_page[1]; - } else { - $pagedList = false; - } - - // Add the new page contacts - $returnedContacts = array_merge($returnedContacts, $response['data']); - } - - $contacts = []; - foreach ($returnedContacts as $item) { - - $uc = new Hybrid_User_Contact(); - $uc->identifier = (array_key_exists("id", $item)) ? $item["id"] : ""; - $uc->displayName = (array_key_exists("name", $item)) ? $item["name"] : ""; - $uc->profileURL = (array_key_exists("link", $item)) ? $item["link"] : "https://www.facebook.com/profile.php?id=" . $uc->identifier; - $uc->photoURL = $this->getUserPhoto($uc->identifier); - - $contacts[] = $uc; - } - - return $contacts; - } - - /** - * Load the user latest activity, needs 'read_stream' permission - * - * @param string $stream Which activity to fetch: - * - timeline : all the stream - * - me : the user activity only - * {@inheritdoc} - */ - function getUserActivity($stream = 'timeline') { - try { - if ($stream == "me") { - $response = $this->api->get('/me/feed', $this->token('access_token')); - } else { - $response = $this->api->get('/me/home', $this->token('access_token')); - } - $response = $response->getDecodedBody(); - } catch (FacebookSDKException $e) { - throw new Hybrid_Exception("User activity stream request failed! {$this->providerId} returned an error: {$e->getMessage()}", 0, $e); - } - - if (!$response || !count($response['data'])) { - return []; - } - - $activities = []; - foreach ($response['data'] as $item) { - - $ua = new Hybrid_User_Activity(); - - $ua->id = (array_key_exists("id", $item)) ? $item["id"] : ""; - $ua->date = (array_key_exists("created_time", $item)) ? strtotime($item["created_time"]) : ""; - - if ($item["type"] == "video") { - $ua->text = (array_key_exists("link", $item)) ? $item["link"] : ""; - } - - if ($item["type"] == "link") { - $ua->text = (array_key_exists("link", $item)) ? $item["link"] : ""; - } - - if (empty($ua->text) && isset($item["story"])) { - $ua->text = (array_key_exists("link", $item)) ? $item["link"] : ""; - } - - if (empty($ua->text) && isset($item["message"])) { - $ua->text = (array_key_exists("message", $item)) ? $item["message"] : ""; - } - - if (!empty($ua->text)) { - $ua->user->identifier = (array_key_exists("id", $item["from"])) ? $item["from"]["id"] : ""; - $ua->user->displayName = (array_key_exists("name", $item["from"])) ? $item["from"]["name"] : ""; - $ua->user->profileURL = "https://www.facebook.com/profile.php?id=" . $ua->user->identifier; - $ua->user->photoURL = $this->getUserPhoto($ua->user->identifier); - - $activities[] = $ua; - } - } - - return $activities; - } - - /** - * Returns a photo URL for give user. - * - * @param string $id - * The User ID. - * - * @return string - * A photo URL. - */ - function getUserPhoto($id) { - $photo_size = isset($this->config['photo_size']) ? $this->config['photo_size'] : 150; - - return "https://graph.facebook.com/{$id}/picture?width={$photo_size}&height={$photo_size}"; - } - -} +config["keys"]["id"] || !$this->config["keys"]["secret"]) { + throw new Exception("Your application id and secret are required in order to connect to {$this->providerId}.", 4); + } + + if (isset($this->config['scope'])) { + $scope = $this->config['scope']; + if (is_string($scope)) { + $scope = explode(",", $scope); + } + $scope = array_map('trim', $scope); + $this->scope = $scope; + } + + $trustForwarded = isset($this->config['trustForwarded']) ? (bool)$this->config['trustForwarded'] : false; + + // Check if there is Graph SDK in thirdparty/Facebook. + if (file_exists(Hybrid_Auth::$config["path_libraries"] . "Facebook/autoload.php")) { + require_once Hybrid_Auth::$config["path_libraries"] . "Facebook/autoload.php"; + } + else { + // If Composer install was executed, try to find autoload.php. + $vendorDir = dirname(Hybrid_Auth::$config['path_base']); + do { + if (file_exists($vendorDir . "/vendor/autoload.php")) { + require_once $vendorDir . "/vendor/autoload.php"; + break; + } + } while (($vendorDir = dirname($vendorDir)) !== '/'); + } + + $this->api = new FacebookSDK([ + 'app_id' => $this->config["keys"]["id"], + 'app_secret' => $this->config["keys"]["secret"], + 'default_graph_version' => 'v2.8', + 'trustForwarded' => $trustForwarded, + ]); + } + + /** + * {@inheritdoc} + */ + function loginBegin() { + + $this->endpoint = $this->params['login_done']; + $helper = $this->api->getRedirectLoginHelper(); + + // Use re-request, because this will trigger permissions window if not all permissions are granted. + $url = $helper->getReRequestUrl($this->endpoint, $this->scope); + + // Redirect to Facebook + Hybrid_Auth::redirect($url); + } + + /** + * {@inheritdoc} + */ + function loginFinish() { + + $helper = $this->api->getRedirectLoginHelper(); + try { + $accessToken = $helper->getAccessToken($this->params['login_done']); + } catch (Facebook\Exceptions\FacebookResponseException $e) { + throw new Hybrid_Exception('Facebook Graph returned an error: ' . $e->getMessage()); + } catch (Facebook\Exceptions\FacebookSDKException $e) { + throw new Hybrid_Exception('Facebook SDK returned an error: ' . $e->getMessage()); + } + + if (!isset($accessToken)) { + if ($helper->getError()) { + throw new Hybrid_Exception(sprintf("Could not authorize user, reason: %s (%d)", $helper->getErrorDescription(), $helper->getErrorCode())); + } else { + throw new Hybrid_Exception("Could not authorize user. Bad request"); + } + } + + try { + // Validate token + $oAuth2Client = $this->api->getOAuth2Client(); + $tokenMetadata = $oAuth2Client->debugToken($accessToken); + $tokenMetadata->validateAppId($this->config["keys"]["id"]); + $tokenMetadata->validateExpiration(); + + // Exchanges a short-lived access token for a long-lived one + if (!$accessToken->isLongLived()) { + $accessToken = $oAuth2Client->getLongLivedAccessToken($accessToken); + } + } catch (FacebookSDKException $e) { + throw new Hybrid_Exception($e->getMessage(), 0, $e); + } + + $this->setUserConnected(); + $this->token("access_token", $accessToken->getValue()); + } + + /** + * {@inheritdoc} + */ + function logout() { + parent::logout(); + } + + /** + * Update user status + * + * @param mixed $status An array describing the status, or string + * @param string $pageid (optional) User page id + * @return array + * @throw Exception + */ + function setUserStatus($status, $pageid = null) { + + if (!is_array($status)) { + $status = array('message' => $status); + } + + $access_token = null; + + if (is_null($pageid)) { + $pageid = 'me'; + $access_token = $this->token('access_token'); + + // if post on page, get access_token page + } else { + + foreach ($this->getUserPages(true) as $p) { + if (isset($p['id']) && intval($p['id']) == intval($pageid)) { + $access_token = $p['access_token']; + break; + } + } + + if (is_null($access_token)) { + throw new Exception("Update user page failed, page not found or not writable!"); + } + } + + try { + $response = $this->api->post('/' . $pageid . '/feed', $status, $access_token); + } catch (FacebookSDKException $e) { + throw new Exception("Update user status failed! {$this->providerId} returned an error {$e->getMessage()}", 0, $e); + } + + return $response; + } + + /** + * {@inheridoc} + */ + function getUserPages($writableonly = false) { + if (( isset($this->config['scope']) && strpos($this->config['scope'], 'manage_pages') === false ) || (!isset($this->config['scope']) && strpos($this->scope, 'manage_pages') === false )) + throw new Exception("User status requires manage_page permission!"); + + try { + $pages = $this->api->get("/me/accounts", $this->token('access_token')); + $pages = $pages->getDecodedBody(); + } catch (FacebookApiException $e) { + throw new Exception("Cannot retrieve user pages! {$this->providerId} returned an error: {$e->getMessage()}", 0, $e); + } + + if (!isset($pages['data'])) { + return array(); + } + + if (!$writableonly) { + return $pages['data']; + } + + $wrpages = array(); + foreach ($pages['data'] as $p) { + if (isset($p['perms']) && in_array('CREATE_CONTENT', $p['perms'])) { + $wrpages[] = $p; + } + } + + return $wrpages; + } + + /** + * {@inheritdoc} + */ + function getUserProfile() { + try { + $fields = [ + 'id', + 'name', + 'first_name', + 'last_name', + 'link', + 'website', + 'gender', + 'locale', + 'about', + 'email', + 'hometown', + 'location', + 'birthday' + ]; + $response = $this->api->get('/me?fields=' . implode(',', $fields), $this->token('access_token')); + $data = $response->getDecodedBody(); + } catch (FacebookSDKException $e) { + throw new Exception("User profile request failed! {$this->providerId} returned an error: {$e->getMessage()}", 6, $e); + } + + // Store the user profile. + $this->user->profile->identifier = (array_key_exists('id', $data)) ? $data['id'] : ""; + $this->user->profile->displayName = (array_key_exists('name', $data)) ? $data['name'] : ""; + $this->user->profile->firstName = (array_key_exists('first_name', $data)) ? $data['first_name'] : ""; + $this->user->profile->lastName = (array_key_exists('last_name', $data)) ? $data['last_name'] : ""; + $this->user->profile->photoURL = $this->getUserPhoto($this->user->profile->identifier); + $this->user->profile->profileURL = (array_key_exists('link', $data)) ? $data['link'] : ""; + $this->user->profile->webSiteURL = (array_key_exists('website', $data)) ? $data['website'] : ""; + $this->user->profile->gender = (array_key_exists('gender', $data)) ? $data['gender'] : ""; + $this->user->profile->language = (array_key_exists('locale', $data)) ? $data['locale'] : ""; + $this->user->profile->description = (array_key_exists('about', $data)) ? $data['about'] : ""; + $this->user->profile->email = (array_key_exists('email', $data)) ? $data['email'] : ""; + $this->user->profile->emailVerified = (array_key_exists('email', $data)) ? $data['email'] : ""; + $this->user->profile->region = (array_key_exists("location", $data) && array_key_exists("name", $data['location'])) ? $data['location']["name"] : ""; + + if (!empty($this->user->profile->region)) { + $regionArr = explode(',', $this->user->profile->region); + if (count($regionArr) > 1) { + $this->user->profile->city = trim($regionArr[0]); + $this->user->profile->country = trim(end($regionArr)); + } + } + + if (array_key_exists('birthday', $data)) { + $birtydayPieces = explode('/', $data['birthday']); + + if (count($birtydayPieces) == 1) { + $this->user->profile->birthYear = (int)$birtydayPieces[0]; + } elseif (count($birtydayPieces) == 2) { + $this->user->profile->birthMonth = (int)$birtydayPieces[0]; + $this->user->profile->birthDay = (int)$birtydayPieces[1]; + } elseif (count($birtydayPieces) == 3) { + $this->user->profile->birthMonth = (int)$birtydayPieces[0]; + $this->user->profile->birthDay = (int)$birtydayPieces[1]; + $this->user->profile->birthYear = (int)$birtydayPieces[2]; + } + } + + return $this->user->profile; + } + + /** + * Since the Graph API 2.0, the /friends endpoint only returns friend that also use your Facebook app. + * {@inheritdoc} + */ + function getUserContacts() { + $apiCall = '?fields=link,name'; + $returnedContacts = []; + $pagedList = true; + + while ($pagedList) { + try { + $response = $this->api->get('/me/friends' . $apiCall, $this->token('access_token')); + $response = $response->getDecodedBody(); + } catch (FacebookSDKException $e) { + throw new Hybrid_Exception("User contacts request failed! {$this->providerId} returned an error {$e->getMessage()}", 0, $e); + } + + // Prepare the next call if paging links have been returned + if (array_key_exists('paging', $response) && array_key_exists('next', $response['paging'])) { + $pagedList = true; + $next_page = explode('friends', $response['paging']['next']); + $apiCall = $next_page[1]; + } else { + $pagedList = false; + } + + // Add the new page contacts + $returnedContacts = array_merge($returnedContacts, $response['data']); + } + + $contacts = []; + foreach ($returnedContacts as $item) { + + $uc = new Hybrid_User_Contact(); + $uc->identifier = (array_key_exists("id", $item)) ? $item["id"] : ""; + $uc->displayName = (array_key_exists("name", $item)) ? $item["name"] : ""; + $uc->profileURL = (array_key_exists("link", $item)) ? $item["link"] : "https://www.facebook.com/profile.php?id=" . $uc->identifier; + $uc->photoURL = $this->getUserPhoto($uc->identifier); + + $contacts[] = $uc; + } + + return $contacts; + } + + /** + * Load the user latest activity, needs 'read_stream' permission + * + * @param string $stream Which activity to fetch: + * - timeline : all the stream + * - me : the user activity only + * {@inheritdoc} + */ + function getUserActivity($stream = 'timeline') { + try { + if ($stream == "me") { + $response = $this->api->get('/me/feed', $this->token('access_token')); + } else { + $response = $this->api->get('/me/home', $this->token('access_token')); + } + $response = $response->getDecodedBody(); + } catch (FacebookSDKException $e) { + throw new Hybrid_Exception("User activity stream request failed! {$this->providerId} returned an error: {$e->getMessage()}", 0, $e); + } + + if (!$response || !count($response['data'])) { + return []; + } + + $activities = []; + foreach ($response['data'] as $item) { + + $ua = new Hybrid_User_Activity(); + + $ua->id = (array_key_exists("id", $item)) ? $item["id"] : ""; + $ua->date = (array_key_exists("created_time", $item)) ? strtotime($item["created_time"]) : ""; + + if ($item["type"] == "video") { + $ua->text = (array_key_exists("link", $item)) ? $item["link"] : ""; + } + + if ($item["type"] == "link") { + $ua->text = (array_key_exists("link", $item)) ? $item["link"] : ""; + } + + if (empty($ua->text) && isset($item["story"])) { + $ua->text = (array_key_exists("link", $item)) ? $item["link"] : ""; + } + + if (empty($ua->text) && isset($item["message"])) { + $ua->text = (array_key_exists("message", $item)) ? $item["message"] : ""; + } + + if (!empty($ua->text)) { + $ua->user->identifier = (array_key_exists("id", $item["from"])) ? $item["from"]["id"] : ""; + $ua->user->displayName = (array_key_exists("name", $item["from"])) ? $item["from"]["name"] : ""; + $ua->user->profileURL = "https://www.facebook.com/profile.php?id=" . $ua->user->identifier; + $ua->user->photoURL = $this->getUserPhoto($ua->user->identifier); + + $activities[] = $ua; + } + } + + return $activities; + } + + /** + * Returns a photo URL for give user. + * + * @param string $id + * The User ID. + * + * @return string + * A photo URL. + */ + function getUserPhoto($id) { + $photo_size = isset($this->config['photo_size']) ? $this->config['photo_size'] : 150; + + return "https://graph.facebook.com/{$id}/picture?width={$photo_size}&height={$photo_size}"; + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Providers/Foursquare.php b/e107_handlers/hybridauth/Hybrid/Providers/Foursquare.php index 5c64e969e..b1156804a 100644 --- a/e107_handlers/hybridauth/Hybrid/Providers/Foursquare.php +++ b/e107_handlers/hybridauth/Hybrid/Providers/Foursquare.php @@ -1,121 +1,121 @@ - array ( - * "enabled" => true, - * "keys" => ..., - * "params" => array( "photo_size" => "16x16" ) - * ), - * ... - * - list of valid photo_size values is described here https://developer.foursquare.com/docs/responses/photo.html - * - default photo_size is 100x100 - */ -class Hybrid_Providers_Foursquare extends Hybrid_Provider_Model_OAuth2 { - - private static $apiVersion = array("v" => "20120610"); - private static $defPhotoSize = "100x100"; - - /** - * {@inheritdoc} - */ - function initialize() { - parent::initialize(); - - // Provider apis end-points - $this->api->api_base_url = "https://api.foursquare.com/v2/"; - $this->api->authorize_url = "https://foursquare.com/oauth2/authenticate"; - $this->api->token_url = "https://foursquare.com/oauth2/access_token"; - - $this->api->sign_token_name = "oauth_token"; - } - - /** - * {@inheritdoc} - */ - function getUserProfile() { - $data = $this->api->api("users/self", "GET", Hybrid_Providers_Foursquare::$apiVersion); - - if (!isset($data->response->user->id)) { - throw new Exception("User profile request failed! {$this->providerId} returned an invalid response:" . Hybrid_Logger::dumpData( $data ), 6); - } - - $data = $data->response->user; - - $this->user->profile->identifier = $data->id; - $this->user->profile->firstName = $data->firstName; - $this->user->profile->lastName = $data->lastName; - $this->user->profile->displayName = $this->buildDisplayName($this->user->profile->firstName, $this->user->profile->lastName); - $this->user->profile->photoURL = $this->buildPhotoURL($data->photo->prefix, $data->photo->suffix); - $this->user->profile->profileURL = "https://www.foursquare.com/user/" . $data->id; - $this->user->profile->gender = $data->gender; - $this->user->profile->city = $data->homeCity; - $this->user->profile->email = $data->contact->email; - $this->user->profile->emailVerified = $data->contact->email; - - return $this->user->profile; - } - - /** - * {@inheritdoc} - */ - function getUserContacts() { - // refresh tokens if needed - $this->refreshToken(); - - // - $response = array(); - $contacts = array(); - try { - $response = $this->api->api("users/self/friends", "GET", Hybrid_Providers_Foursquare::$apiVersion); - } catch (Exception $e) { - throw new Exception("User contacts request failed! {$this->providerId} returned an error: {$e->getMessage()}", 0, $e); - } - - if (isset($response) && $response->meta->code == 200) { - foreach ($response->response->friends->items as $contact) { - $uc = new Hybrid_User_Contact(); - // - $uc->identifier = $contact->id; - //$uc->profileURL = ; - //$uc->webSiteURL = ; - $uc->photoURL = $this->buildPhotoURL($contact->photo->prefix, $contact->photo->suffix); - $uc->displayName = $this->buildDisplayName((isset($contact->firstName) ? ($contact->firstName) : ("")), (isset($contact->lastName) ? ($contact->lastName) : (""))); - //$uc->description = ; - $uc->email = (isset($contact->contact->email) ? ($contact->contact->email) : ("")); - // - $contacts[] = $uc; - } - } - return $contacts; - } - - /** - * {@inheritdoc} - */ - private function buildDisplayName($firstName, $lastName) { - return trim($firstName . " " . $lastName); - } - - private function buildPhotoURL($prefix, $suffix) { - if (isset($prefix) && isset($suffix)) { - return $prefix . ((isset($this->config["params"]["photo_size"])) ? ($this->config["params"]["photo_size"]) : (Hybrid_Providers_Foursquare::$defPhotoSize)) . $suffix; - } - return (""); - } - -} + array ( + * "enabled" => true, + * "keys" => ..., + * "params" => array( "photo_size" => "16x16" ) + * ), + * ... + * - list of valid photo_size values is described here https://developer.foursquare.com/docs/responses/photo.html + * - default photo_size is 100x100 + */ +class Hybrid_Providers_Foursquare extends Hybrid_Provider_Model_OAuth2 { + + private static $apiVersion = array("v" => "20120610"); + private static $defPhotoSize = "100x100"; + + /** + * {@inheritdoc} + */ + function initialize() { + parent::initialize(); + + // Provider apis end-points + $this->api->api_base_url = "https://api.foursquare.com/v2/"; + $this->api->authorize_url = "https://foursquare.com/oauth2/authenticate"; + $this->api->token_url = "https://foursquare.com/oauth2/access_token"; + + $this->api->sign_token_name = "oauth_token"; + } + + /** + * {@inheritdoc} + */ + function getUserProfile() { + $data = $this->api->api("users/self", "GET", Hybrid_Providers_Foursquare::$apiVersion); + + if (!isset($data->response->user->id)) { + throw new Exception("User profile request failed! {$this->providerId} returned an invalid response:" . Hybrid_Logger::dumpData( $data ), 6); + } + + $data = $data->response->user; + + $this->user->profile->identifier = $data->id; + $this->user->profile->firstName = $data->firstName; + $this->user->profile->lastName = $data->lastName; + $this->user->profile->displayName = $this->buildDisplayName($this->user->profile->firstName, $this->user->profile->lastName); + $this->user->profile->photoURL = $this->buildPhotoURL($data->photo->prefix, $data->photo->suffix); + $this->user->profile->profileURL = "https://www.foursquare.com/user/" . $data->id; + $this->user->profile->gender = $data->gender; + $this->user->profile->city = $data->homeCity; + $this->user->profile->email = $data->contact->email; + $this->user->profile->emailVerified = $data->contact->email; + + return $this->user->profile; + } + + /** + * {@inheritdoc} + */ + function getUserContacts() { + // refresh tokens if needed + $this->refreshToken(); + + // + $response = array(); + $contacts = array(); + try { + $response = $this->api->api("users/self/friends", "GET", Hybrid_Providers_Foursquare::$apiVersion); + } catch (Exception $e) { + throw new Exception("User contacts request failed! {$this->providerId} returned an error: {$e->getMessage()}", 0, $e); + } + + if (isset($response) && $response->meta->code == 200) { + foreach ($response->response->friends->items as $contact) { + $uc = new Hybrid_User_Contact(); + // + $uc->identifier = $contact->id; + //$uc->profileURL = ; + //$uc->webSiteURL = ; + $uc->photoURL = $this->buildPhotoURL($contact->photo->prefix, $contact->photo->suffix); + $uc->displayName = $this->buildDisplayName((isset($contact->firstName) ? ($contact->firstName) : ("")), (isset($contact->lastName) ? ($contact->lastName) : (""))); + //$uc->description = ; + $uc->email = (isset($contact->contact->email) ? ($contact->contact->email) : ("")); + // + $contacts[] = $uc; + } + } + return $contacts; + } + + /** + * {@inheritdoc} + */ + private function buildDisplayName($firstName, $lastName) { + return trim($firstName . " " . $lastName); + } + + private function buildPhotoURL($prefix, $suffix) { + if (isset($prefix) && isset($suffix)) { + return $prefix . ((isset($this->config["params"]["photo_size"])) ? ($this->config["params"]["photo_size"]) : (Hybrid_Providers_Foursquare::$defPhotoSize)) . $suffix; + } + return (""); + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Providers/Google.php b/e107_handlers/hybridauth/Hybrid/Providers/Google.php index 9e650e50a..3c936725f 100644 --- a/e107_handlers/hybridauth/Hybrid/Providers/Google.php +++ b/e107_handlers/hybridauth/Hybrid/Providers/Google.php @@ -1,306 +1,306 @@ - more infos on google APIs: http://developer.google.com (official site) - * or here: http://discovery-check.appspot.com/ (unofficial but up to date) - * default permissions - * {@inheritdoc} - */ - public $scope = "https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/plus.profile.emails.read https://www.google.com/m8/feeds/"; - - /** - * {@inheritdoc} - */ - function initialize() { - parent::initialize(); - - // Provider api end-points - $this->api->authorize_url = "https://accounts.google.com/o/oauth2/auth"; - $this->api->token_url = "https://accounts.google.com/o/oauth2/token"; - $this->api->token_info_url = "https://www.googleapis.com/oauth2/v2/tokeninfo"; - - // Google POST methods require an access_token in the header - $this->api->curl_header = array("Authorization: OAuth " . $this->api->access_token); - - // Override the redirect uri when it's set in the config parameters. This way we prevent - // redirect uri mismatches when authenticating with Google. - if (isset($this->config['redirect_uri']) && !empty($this->config['redirect_uri'])) { - $this->api->redirect_uri = $this->config['redirect_uri']; - } - } - - /** - * {@inheritdoc} - */ - function loginBegin() { - $parameters = array("scope" => $this->scope, "access_type" => "offline"); - $optionals = array("scope", "access_type", "redirect_uri", "approval_prompt", "hd", "state"); - - foreach ($optionals as $parameter) { - if (isset($this->config[$parameter]) && !empty($this->config[$parameter])) { - $parameters[$parameter] = $this->config[$parameter]; - } - if (isset($this->config["scope"]) && !empty($this->config["scope"])) { - $this->scope = $this->config["scope"]; - } - } - - if (isset($this->config['force']) && $this->config['force'] === true) { - $parameters['approval_prompt'] = 'force'; - } - - Hybrid_Auth::redirect($this->api->authorizeUrl($parameters)); - } - - /** - * {@inheritdoc} - */ - function getUserProfile() { - // refresh tokens if needed - $this->refreshToken(); - - // ask google api for user infos - if (strpos($this->scope, '/auth/plus.profile.emails.read') !== false) { - $verified = $this->api->api("https://www.googleapis.com/plus/v1/people/me"); - - if (!isset($verified->id) || isset($verified->error)) - $verified = new stdClass(); - } else { - $verified = $this->api->api("https://www.googleapis.com/plus/v1/people/me/openIdConnect"); - - if (!isset($verified->sub) || isset($verified->error)) - $verified = new stdClass(); - } - - $response = $this->api->api("https://www.googleapis.com/plus/v1/people/me"); - if (!isset($response->id) || isset($response->error)) { - throw new Exception("User profile request failed! {$this->providerId} returned an invalid response:" . Hybrid_Logger::dumpData( $response ), 6); - } - - $this->user->profile->identifier = (property_exists($verified, 'id')) ? $verified->id : ((property_exists($response, 'id')) ? $response->id : ""); - $this->user->profile->firstName = (property_exists($response, 'name')) ? $response->name->givenName : ""; - $this->user->profile->lastName = (property_exists($response, 'name')) ? $response->name->familyName : ""; - $this->user->profile->displayName = (property_exists($response, 'displayName')) ? $response->displayName : ""; - $this->user->profile->photoURL = (property_exists($response, 'image')) ? ((property_exists($response->image, 'url')) ? substr($response->image->url, 0, -2) . "200" : '') : ''; - $this->user->profile->profileURL = (property_exists($response, 'url')) ? $response->url : ""; - $this->user->profile->description = (property_exists($response, 'aboutMe')) ? $response->aboutMe : ""; - $this->user->profile->gender = (property_exists($response, 'gender')) ? $response->gender : ""; - $this->user->profile->language = (property_exists($response, 'locale')) ? $response->locale : ((property_exists($verified, 'locale')) ? $verified->locale : ""); - $this->user->profile->email = (property_exists($response, 'email')) ? $response->email : ((property_exists($verified, 'email')) ? $verified->email : ""); - $this->user->profile->emailVerified = (property_exists($verified, 'email')) ? $verified->email : ""; - if (property_exists($response, 'emails')) { - if (count($response->emails) == 1) { - $this->user->profile->email = $response->emails[0]->value; - } else { - foreach ($response->emails as $email) { - if ($email->type == 'account') { - $this->user->profile->email = $email->value; - break; - } - } - } - if (property_exists($verified, 'emails')) { - if (count($verified->emails) == 1) { - $this->user->profile->emailVerified = $verified->emails[0]->value; - } else { - foreach ($verified->emails as $email) { - if ($email->type == 'account') { - $this->user->profile->emailVerified = $email->value; - break; - } - } - } - } - } - $this->user->profile->phone = (property_exists($response, 'phone')) ? $response->phone : ""; - $this->user->profile->country = (property_exists($response, 'country')) ? $response->country : ""; - $this->user->profile->region = (property_exists($response, 'region')) ? $response->region : ""; - $this->user->profile->zip = (property_exists($response, 'zip')) ? $response->zip : ""; - if (property_exists($response, 'placesLived')) { - $this->user->profile->city = ""; - $this->user->profile->address = ""; - foreach ($response->placesLived as $c) { - if (property_exists($c, 'primary')) { - if ($c->primary == true) { - $this->user->profile->address = $c->value; - $this->user->profile->city = $c->value; - break; - } - } else { - if (property_exists($c, 'value')) { - $this->user->profile->address = $c->value; - $this->user->profile->city = $c->value; - } - } - } - } - - // google API returns multiple urls, but a "website" only if it is verified - // see http://support.google.com/plus/answer/1713826?hl=en - if (property_exists($response, 'urls')) { - foreach ($response->urls as $u) { - if (property_exists($u, 'primary') && $u->primary == true) - $this->user->profile->webSiteURL = $u->value; - } - } else { - $this->user->profile->webSiteURL = ''; - } - // google API returns age ranges min and/or max as of https://developers.google.com/+/web/api/rest/latest/people#resource - if (property_exists($response, 'ageRange')) { - if (property_exists($response->ageRange, 'min') && property_exists($response->ageRange, 'max')) { - $this->user->profile->age = $response->ageRange->min . ' - ' . $response->ageRange->max; - } else { - if (property_exists($response->ageRange, 'min')) { - $this->user->profile->age = '>= ' . $response->ageRange->min; - } else { - if (property_exists($response->ageRange, 'max')) { - $this->user->profile->age = '<= ' . $response->ageRange->max; - } else { - $this->user->profile->age = ''; - } - } - } - } else { - $this->user->profile->age = ''; - } - // google API returns birthdays only if a user set 'show in my account' - if (property_exists($response, 'birthday')) { - list($birthday_year, $birthday_month, $birthday_day) = explode('-', $response->birthday); - - $this->user->profile->birthDay = (int) $birthday_day; - $this->user->profile->birthMonth = (int) $birthday_month; - $this->user->profile->birthYear = (int) $birthday_year; - } else { - $this->user->profile->birthDay = 0; - $this->user->profile->birthMonth = 0; - $this->user->profile->birthYear = 0; - } - - return $this->user->profile; - } - - /** - * {@inheritdoc} - */ - function getUserContacts() { - // refresh tokens if needed - $this->refreshToken(); - - $contacts = array(); - if (!isset($this->config['contacts_param'])) { - $this->config['contacts_param'] = array("max-results" => 500); - } - - // Google Gmail and Android contacts - if (strpos($this->scope, '/m8/feeds/') !== false) { - - $response = $this->api->api("https://www.google.com/m8/feeds/contacts/default/full?" - . http_build_query(array_merge(array('alt' => 'json'), $this->config['contacts_param']))); - - if (!$response) { - return array(); - } - - if (isset($response->feed->entry)) { - foreach ($response->feed->entry as $idx => $entry) { - $uc = new Hybrid_User_Contact(); - $uc->email = isset($entry->{'gd$email'}[0]->address) ? (string) $entry->{'gd$email'}[0]->address : ''; - $uc->displayName = isset($entry->title->{'$t'}) ? (string) $entry->title->{'$t'} : ''; - $uc->identifier = ($uc->email != '') ? $uc->email : ''; - $uc->description = ''; - if (property_exists($entry, 'link')) { - /** - * sign links with access_token - */ - if (is_array($entry->link)) { - foreach ($entry->link as $l) { - if (property_exists($l, 'gd$etag') && $l->type == "image/*") { - $uc->photoURL = $this->addUrlParam($l->href, array('access_token' => $this->api->access_token)); - } else if ($l->type == "self") { - $uc->profileURL = $this->addUrlParam($l->href, array('access_token' => $this->api->access_token)); - } - } - } - } else { - $uc->profileURL = ''; - } - if (property_exists($response, 'website')) { - if (is_array($response->website)) { - foreach ($response->website as $w) { - if ($w->primary == true) - $uc->webSiteURL = $w->value; - } - } else { - $uc->webSiteURL = $response->website->value; - } - } else { - $uc->webSiteURL = ''; - } - - $contacts[] = $uc; - } - } - } - - // Google social contacts - if (strpos($this->scope, '/auth/plus.login') !== false) { - - $response = $this->api->api("https://www.googleapis.com/plus/v1/people/me/people/visible?" - . http_build_query($this->config['contacts_param'])); - - if (!$response) { - return array(); - } - - foreach ($response->items as $idx => $item) { - $uc = new Hybrid_User_Contact(); - $uc->email = (property_exists($item, 'email')) ? $item->email : ''; - $uc->displayName = (property_exists($item, 'displayName')) ? $item->displayName : ''; - $uc->identifier = (property_exists($item, 'id')) ? $item->id : ''; - - $uc->description = (property_exists($item, 'objectType')) ? $item->objectType : ''; - $uc->photoURL = (property_exists($item, 'image')) ? ((property_exists($item->image, 'url')) ? $item->image->url : '') : ''; - $uc->profileURL = (property_exists($item, 'url')) ? $item->url : ''; - $uc->webSiteURL = ''; - - $contacts[] = $uc; - } - } - - return $contacts; - } - - /** - * Add query parameters to the $url - * - * @param string $url URL - * @param array $params Parameters to add - * @return string - */ - function addUrlParam($url, array $params){ - $query = parse_url($url, PHP_URL_QUERY); - - // Returns the URL string with new parameters - if ($query) { - $url .= '&' . http_build_query($params); - } else { - $url .= '?' . http_build_query($params); - } - return $url; - } - -} - + more infos on google APIs: http://developer.google.com (official site) + * or here: http://discovery-check.appspot.com/ (unofficial but up to date) + * default permissions + * {@inheritdoc} + */ + public $scope = "https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/plus.profile.emails.read https://www.google.com/m8/feeds/"; + + /** + * {@inheritdoc} + */ + function initialize() { + parent::initialize(); + + // Provider api end-points + $this->api->authorize_url = "https://accounts.google.com/o/oauth2/auth"; + $this->api->token_url = "https://accounts.google.com/o/oauth2/token"; + $this->api->token_info_url = "https://www.googleapis.com/oauth2/v2/tokeninfo"; + + // Google POST methods require an access_token in the header + $this->api->curl_header = array("Authorization: OAuth " . $this->api->access_token); + + // Override the redirect uri when it's set in the config parameters. This way we prevent + // redirect uri mismatches when authenticating with Google. + if (isset($this->config['redirect_uri']) && !empty($this->config['redirect_uri'])) { + $this->api->redirect_uri = $this->config['redirect_uri']; + } + } + + /** + * {@inheritdoc} + */ + function loginBegin() { + $parameters = array("scope" => $this->scope, "access_type" => "offline"); + $optionals = array("scope", "access_type", "redirect_uri", "approval_prompt", "hd", "state"); + + foreach ($optionals as $parameter) { + if (isset($this->config[$parameter]) && !empty($this->config[$parameter])) { + $parameters[$parameter] = $this->config[$parameter]; + } + if (isset($this->config["scope"]) && !empty($this->config["scope"])) { + $this->scope = $this->config["scope"]; + } + } + + if (isset($this->config['force']) && $this->config['force'] === true) { + $parameters['approval_prompt'] = 'force'; + } + + Hybrid_Auth::redirect($this->api->authorizeUrl($parameters)); + } + + /** + * {@inheritdoc} + */ + function getUserProfile() { + // refresh tokens if needed + $this->refreshToken(); + + // ask google api for user infos + if (strpos($this->scope, '/auth/plus.profile.emails.read') !== false) { + $verified = $this->api->api("https://www.googleapis.com/plus/v1/people/me"); + + if (!isset($verified->id) || isset($verified->error)) + $verified = new stdClass(); + } else { + $verified = $this->api->api("https://www.googleapis.com/plus/v1/people/me/openIdConnect"); + + if (!isset($verified->sub) || isset($verified->error)) + $verified = new stdClass(); + } + + $response = $this->api->api("https://www.googleapis.com/plus/v1/people/me"); + if (!isset($response->id) || isset($response->error)) { + throw new Exception("User profile request failed! {$this->providerId} returned an invalid response:" . Hybrid_Logger::dumpData( $response ), 6); + } + + $this->user->profile->identifier = (property_exists($verified, 'id')) ? $verified->id : ((property_exists($response, 'id')) ? $response->id : ""); + $this->user->profile->firstName = (property_exists($response, 'name')) ? $response->name->givenName : ""; + $this->user->profile->lastName = (property_exists($response, 'name')) ? $response->name->familyName : ""; + $this->user->profile->displayName = (property_exists($response, 'displayName')) ? $response->displayName : ""; + $this->user->profile->photoURL = (property_exists($response, 'image')) ? ((property_exists($response->image, 'url')) ? substr($response->image->url, 0, -2) . "200" : '') : ''; + $this->user->profile->profileURL = (property_exists($response, 'url')) ? $response->url : ""; + $this->user->profile->description = (property_exists($response, 'aboutMe')) ? $response->aboutMe : ""; + $this->user->profile->gender = (property_exists($response, 'gender')) ? $response->gender : ""; + $this->user->profile->language = (property_exists($response, 'locale')) ? $response->locale : ((property_exists($verified, 'locale')) ? $verified->locale : ""); + $this->user->profile->email = (property_exists($response, 'email')) ? $response->email : ((property_exists($verified, 'email')) ? $verified->email : ""); + $this->user->profile->emailVerified = (property_exists($verified, 'email')) ? $verified->email : ""; + if (property_exists($response, 'emails')) { + if (count($response->emails) == 1) { + $this->user->profile->email = $response->emails[0]->value; + } else { + foreach ($response->emails as $email) { + if ($email->type == 'account') { + $this->user->profile->email = $email->value; + break; + } + } + } + if (property_exists($verified, 'emails')) { + if (count($verified->emails) == 1) { + $this->user->profile->emailVerified = $verified->emails[0]->value; + } else { + foreach ($verified->emails as $email) { + if ($email->type == 'account') { + $this->user->profile->emailVerified = $email->value; + break; + } + } + } + } + } + $this->user->profile->phone = (property_exists($response, 'phone')) ? $response->phone : ""; + $this->user->profile->country = (property_exists($response, 'country')) ? $response->country : ""; + $this->user->profile->region = (property_exists($response, 'region')) ? $response->region : ""; + $this->user->profile->zip = (property_exists($response, 'zip')) ? $response->zip : ""; + if (property_exists($response, 'placesLived')) { + $this->user->profile->city = ""; + $this->user->profile->address = ""; + foreach ($response->placesLived as $c) { + if (property_exists($c, 'primary')) { + if ($c->primary == true) { + $this->user->profile->address = $c->value; + $this->user->profile->city = $c->value; + break; + } + } else { + if (property_exists($c, 'value')) { + $this->user->profile->address = $c->value; + $this->user->profile->city = $c->value; + } + } + } + } + + // google API returns multiple urls, but a "website" only if it is verified + // see http://support.google.com/plus/answer/1713826?hl=en + if (property_exists($response, 'urls')) { + foreach ($response->urls as $u) { + if (property_exists($u, 'primary') && $u->primary == true) + $this->user->profile->webSiteURL = $u->value; + } + } else { + $this->user->profile->webSiteURL = ''; + } + // google API returns age ranges min and/or max as of https://developers.google.com/+/web/api/rest/latest/people#resource + if (property_exists($response, 'ageRange')) { + if (property_exists($response->ageRange, 'min') && property_exists($response->ageRange, 'max')) { + $this->user->profile->age = $response->ageRange->min . ' - ' . $response->ageRange->max; + } else { + if (property_exists($response->ageRange, 'min')) { + $this->user->profile->age = '>= ' . $response->ageRange->min; + } else { + if (property_exists($response->ageRange, 'max')) { + $this->user->profile->age = '<= ' . $response->ageRange->max; + } else { + $this->user->profile->age = ''; + } + } + } + } else { + $this->user->profile->age = ''; + } + // google API returns birthdays only if a user set 'show in my account' + if (property_exists($response, 'birthday')) { + list($birthday_year, $birthday_month, $birthday_day) = explode('-', $response->birthday); + + $this->user->profile->birthDay = (int) $birthday_day; + $this->user->profile->birthMonth = (int) $birthday_month; + $this->user->profile->birthYear = (int) $birthday_year; + } else { + $this->user->profile->birthDay = 0; + $this->user->profile->birthMonth = 0; + $this->user->profile->birthYear = 0; + } + + return $this->user->profile; + } + + /** + * {@inheritdoc} + */ + function getUserContacts() { + // refresh tokens if needed + $this->refreshToken(); + + $contacts = array(); + if (!isset($this->config['contacts_param'])) { + $this->config['contacts_param'] = array("max-results" => 500); + } + + // Google Gmail and Android contacts + if (strpos($this->scope, '/m8/feeds/') !== false) { + + $response = $this->api->api("https://www.google.com/m8/feeds/contacts/default/full?" + . http_build_query(array_merge(array('alt' => 'json'), $this->config['contacts_param']))); + + if (!$response) { + return array(); + } + + if (isset($response->feed->entry)) { + foreach ($response->feed->entry as $idx => $entry) { + $uc = new Hybrid_User_Contact(); + $uc->email = isset($entry->{'gd$email'}[0]->address) ? (string) $entry->{'gd$email'}[0]->address : ''; + $uc->displayName = isset($entry->title->{'$t'}) ? (string) $entry->title->{'$t'} : ''; + $uc->identifier = ($uc->email != '') ? $uc->email : ''; + $uc->description = ''; + if (property_exists($entry, 'link')) { + /** + * sign links with access_token + */ + if (is_array($entry->link)) { + foreach ($entry->link as $l) { + if (property_exists($l, 'gd$etag') && $l->type == "image/*") { + $uc->photoURL = $this->addUrlParam($l->href, array('access_token' => $this->api->access_token)); + } else if ($l->type == "self") { + $uc->profileURL = $this->addUrlParam($l->href, array('access_token' => $this->api->access_token)); + } + } + } + } else { + $uc->profileURL = ''; + } + if (property_exists($response, 'website')) { + if (is_array($response->website)) { + foreach ($response->website as $w) { + if ($w->primary == true) + $uc->webSiteURL = $w->value; + } + } else { + $uc->webSiteURL = $response->website->value; + } + } else { + $uc->webSiteURL = ''; + } + + $contacts[] = $uc; + } + } + } + + // Google social contacts + if (strpos($this->scope, '/auth/plus.login') !== false) { + + $response = $this->api->api("https://www.googleapis.com/plus/v1/people/me/people/visible?" + . http_build_query($this->config['contacts_param'])); + + if (!$response) { + return array(); + } + + foreach ($response->items as $idx => $item) { + $uc = new Hybrid_User_Contact(); + $uc->email = (property_exists($item, 'email')) ? $item->email : ''; + $uc->displayName = (property_exists($item, 'displayName')) ? $item->displayName : ''; + $uc->identifier = (property_exists($item, 'id')) ? $item->id : ''; + + $uc->description = (property_exists($item, 'objectType')) ? $item->objectType : ''; + $uc->photoURL = (property_exists($item, 'image')) ? ((property_exists($item->image, 'url')) ? $item->image->url : '') : ''; + $uc->profileURL = (property_exists($item, 'url')) ? $item->url : ''; + $uc->webSiteURL = ''; + + $contacts[] = $uc; + } + } + + return $contacts; + } + + /** + * Add query parameters to the $url + * + * @param string $url URL + * @param array $params Parameters to add + * @return string + */ + function addUrlParam($url, array $params){ + $query = parse_url($url, PHP_URL_QUERY); + + // Returns the URL string with new parameters + if ($query) { + $url .= '&' . http_build_query($params); + } else { + $url .= '?' . http_build_query($params); + } + return $url; + } + +} + diff --git a/e107_handlers/hybridauth/Hybrid/Providers/GoogleOpenID.php b/e107_handlers/hybridauth/Hybrid/Providers/GoogleOpenID.php index f0b3e5627..4d3d3e07f 100644 --- a/e107_handlers/hybridauth/Hybrid/Providers/GoogleOpenID.php +++ b/e107_handlers/hybridauth/Hybrid/Providers/GoogleOpenID.php @@ -1,40 +1,40 @@ - array ( - * "enabled" => true, - * "wrapper" => array( "path" => "Providers/GoogleOpenID.php", "class" => "Hybrid_Providers_Google" ) - * ) - */ -class Hybrid_Providers_Google extends Hybrid_Provider_Model_OpenID -{ - var $openidIdentifier = "https://www.google.com/accounts/o8/id"; - - /** - * finish login step - */ - function loginFinish() - { - parent::loginFinish(); - - $this->user->profile->emailVerified = $this->user->profile->email; - - // restore the user profile - Hybrid_Auth::storage()->set( "hauth_session.{$this->providerId}.user", $this->user ); - } -} + array ( + * "enabled" => true, + * "wrapper" => array( "path" => "Providers/GoogleOpenID.php", "class" => "Hybrid_Providers_Google" ) + * ) + */ +class Hybrid_Providers_Google extends Hybrid_Provider_Model_OpenID +{ + var $openidIdentifier = "https://www.google.com/accounts/o8/id"; + + /** + * finish login step + */ + function loginFinish() + { + parent::loginFinish(); + + $this->user->profile->emailVerified = $this->user->profile->email; + + // restore the user profile + Hybrid_Auth::storage()->set( "hauth_session.{$this->providerId}.user", $this->user ); + } +} diff --git a/e107_handlers/hybridauth/Hybrid/Providers/LinkedIn.php b/e107_handlers/hybridauth/Hybrid/Providers/LinkedIn.php index 2a442b2dc..f74f827f0 100644 --- a/e107_handlers/hybridauth/Hybrid/Providers/LinkedIn.php +++ b/e107_handlers/hybridauth/Hybrid/Providers/LinkedIn.php @@ -1,170 +1,170 @@ -api->api_base_url = "https://api.linkedin.com/v1/"; - $this->api->authorize_url = "https://www.linkedin.com/oauth/v2/authorization"; - $this->api->token_url = "https://www.linkedin.com/oauth/v2/accessToken"; - } - - /** - * {@inheritdoc} - */ - function loginBegin() { - if (is_array($this->scope)) { - $this->scope = implode(" ", $this->scope); - } - parent::loginBegin(); - } - - /** - * {@inheritdoc} - * - * @see https://developer.linkedin.com/docs/rest-api - */ - function getUserProfile() { - // Refresh tokens if needed. - $this->setHeaders("token"); - $this->refreshToken(); - - // https://developer.linkedin.com/docs/fields. - $fields = isset($this->config["fields"]) ? $this->config["fields"] : [ - "id", - "email-address", - "first-name", - "last-name", - "headline", - "location", - "industry", - "picture-url", - "public-profile-url", - ]; - - $this->setHeaders(); - $response = $this->api->get( - "people/~:(" . implode(",", $fields) . ")", - array( - "format" => "json", - ) - ); - - if (!isset($response->id)) { - throw new Exception("User profile request failed! {$this->providerId} returned an invalid response: " . Hybrid_Logger::dumpData($response), 6); - } - - $this->user->profile->identifier = isset($response->id) ? $response->id : ""; - $this->user->profile->firstName = isset($response->firstName) ? $response->firstName : ""; - $this->user->profile->lastName = isset($response->lastName) ? $response->lastName : ""; - $this->user->profile->photoURL = isset($response->pictureUrl) ? $response->pictureUrl : ""; - $this->user->profile->profileURL = isset($response->publicProfileUrl) ? $response->publicProfileUrl : ""; - $this->user->profile->email = isset($response->emailAddress) ? $response->emailAddress : ""; - $this->user->profile->description = isset($response->headline) ? $response->headline : ""; - $this->user->profile->country = isset($response->location) ? $response->location->name : ""; - $this->user->profile->emailVerified = $this->user->profile->email; - $this->user->profile->displayName = trim($this->user->profile->firstName . " " . $this->user->profile->lastName); - - return $this->user->profile; - } - - /** - * {@inheritdoc} - * - * @param array $status - * An associative array containing: - * - content: A collection of fields describing the shared content. - * - comment: A comment by the member to associated with the share. - * - visibility: A collection of visibility information about the share. - * - * @return object - * An object containing: - * - updateKey - A unique ID for the shared content posting that was just created. - * - updateUrl - A direct link to the newly shared content on LinkedIn.com that you can direct the user's web browser to. - * @throws Exception - * @see https://developer.linkedin.com/docs/share-on-linkedin - */ - function setUserStatus($status) { - // Refresh tokens if needed. - $this->setHeaders("token"); - $this->refreshToken(); - - try { - // Define default visibility. - if (!isset($status["visibility"])) { - $status["visibility"]["code"] = "anyone"; - } - - $this->setHeaders("share"); - $response = $this->api->post( - "people/~/shares?format=json", - array( - "body" => $status, - ) - ); - } catch (Exception $e) { - throw new Exception("Update user status failed! {$this->providerId} returned an error: {$e->getMessage()}", 0, $e); - } - - if (!isset($response->updateKey)) { - throw new Exception("Update user status failed! {$this->providerId} returned an error: {$response->message}", $response->errorCode); - } - - return $response; - } - - /** - * Set correct request headers. - * - * @param string $api_type - * (optional) Specify api type. - * - * @return void - */ - private function setHeaders($api_type = null) { - $this->api->curl_header = array( - "Authorization: Bearer {$this->api->access_token}", - ); - - switch ($api_type) { - case "share": - $this->api->curl_header = array_merge( - $this->api->curl_header, - array( - "Content-Type: application/json", - "x-li-format: json", - ) - ); - break; - - case "token": - $this->api->curl_header = array_merge( - $this->api->curl_header, - array( - "Content-Type: application/x-www-form-urlencoded", - ) - ); - break; - } - } - -} +api->api_base_url = "https://api.linkedin.com/v1/"; + $this->api->authorize_url = "https://www.linkedin.com/oauth/v2/authorization"; + $this->api->token_url = "https://www.linkedin.com/oauth/v2/accessToken"; + } + + /** + * {@inheritdoc} + */ + function loginBegin() { + if (is_array($this->scope)) { + $this->scope = implode(" ", $this->scope); + } + parent::loginBegin(); + } + + /** + * {@inheritdoc} + * + * @see https://developer.linkedin.com/docs/rest-api + */ + function getUserProfile() { + // Refresh tokens if needed. + $this->setHeaders("token"); + $this->refreshToken(); + + // https://developer.linkedin.com/docs/fields. + $fields = isset($this->config["fields"]) ? $this->config["fields"] : [ + "id", + "email-address", + "first-name", + "last-name", + "headline", + "location", + "industry", + "picture-url", + "public-profile-url", + ]; + + $this->setHeaders(); + $response = $this->api->get( + "people/~:(" . implode(",", $fields) . ")", + array( + "format" => "json", + ) + ); + + if (!isset($response->id)) { + throw new Exception("User profile request failed! {$this->providerId} returned an invalid response: " . Hybrid_Logger::dumpData($response), 6); + } + + $this->user->profile->identifier = isset($response->id) ? $response->id : ""; + $this->user->profile->firstName = isset($response->firstName) ? $response->firstName : ""; + $this->user->profile->lastName = isset($response->lastName) ? $response->lastName : ""; + $this->user->profile->photoURL = isset($response->pictureUrl) ? $response->pictureUrl : ""; + $this->user->profile->profileURL = isset($response->publicProfileUrl) ? $response->publicProfileUrl : ""; + $this->user->profile->email = isset($response->emailAddress) ? $response->emailAddress : ""; + $this->user->profile->description = isset($response->headline) ? $response->headline : ""; + $this->user->profile->country = isset($response->location) ? $response->location->name : ""; + $this->user->profile->emailVerified = $this->user->profile->email; + $this->user->profile->displayName = trim($this->user->profile->firstName . " " . $this->user->profile->lastName); + + return $this->user->profile; + } + + /** + * {@inheritdoc} + * + * @param array $status + * An associative array containing: + * - content: A collection of fields describing the shared content. + * - comment: A comment by the member to associated with the share. + * - visibility: A collection of visibility information about the share. + * + * @return object + * An object containing: + * - updateKey - A unique ID for the shared content posting that was just created. + * - updateUrl - A direct link to the newly shared content on LinkedIn.com that you can direct the user's web browser to. + * @throws Exception + * @see https://developer.linkedin.com/docs/share-on-linkedin + */ + function setUserStatus($status) { + // Refresh tokens if needed. + $this->setHeaders("token"); + $this->refreshToken(); + + try { + // Define default visibility. + if (!isset($status["visibility"])) { + $status["visibility"]["code"] = "anyone"; + } + + $this->setHeaders("share"); + $response = $this->api->post( + "people/~/shares?format=json", + array( + "body" => $status, + ) + ); + } catch (Exception $e) { + throw new Exception("Update user status failed! {$this->providerId} returned an error: {$e->getMessage()}", 0, $e); + } + + if (!isset($response->updateKey)) { + throw new Exception("Update user status failed! {$this->providerId} returned an error: {$response->message}", $response->errorCode); + } + + return $response; + } + + /** + * Set correct request headers. + * + * @param string $api_type + * (optional) Specify api type. + * + * @return void + */ + private function setHeaders($api_type = null) { + $this->api->curl_header = array( + "Authorization: Bearer {$this->api->access_token}", + ); + + switch ($api_type) { + case "share": + $this->api->curl_header = array_merge( + $this->api->curl_header, + array( + "Content-Type: application/json", + "x-li-format: json", + ) + ); + break; + + case "token": + $this->api->curl_header = array_merge( + $this->api->curl_header, + array( + "Content-Type: application/x-www-form-urlencoded", + ) + ); + break; + } + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Providers/Live.php b/e107_handlers/hybridauth/Hybrid/Providers/Live.php index 0cc295161..da177a30d 100644 --- a/e107_handlers/hybridauth/Hybrid/Providers/Live.php +++ b/e107_handlers/hybridauth/Hybrid/Providers/Live.php @@ -1,100 +1,100 @@ - - * @version 0.2 - * @license BSD License - */ - -/** - * Hybrid_Providers_Live - Windows Live provider adapter based on OAuth2 protocol - */ -class Hybrid_Providers_Live extends Hybrid_Provider_Model_OAuth2 { - - /** - * {@inheritdoc} - */ - public $scope = 'wl.basic wl.contacts_emails wl.emails wl.signin wl.share wl.birthday'; - - /** - * {@inheritdoc} - */ - function initialize() { - parent::initialize(); - - // Provider api end-points - $this->api->api_base_url = 'https://apis.live.net/v5.0/'; - $this->api->authorize_url = 'https://login.live.com/oauth20_authorize.srf'; - $this->api->token_url = 'https://login.live.com/oauth20_token.srf'; - } - - /** - * {@inheritdoc} - */ - function getUserProfile() { - $data = $this->api->get("me"); - - if (!isset($data->id)) { - throw new Exception("User profile request failed! {$this->providerId} returned an invalid response: " . Hybrid_Logger::dumpData( $data ), 6); - } - - $this->user->profile->identifier = (property_exists($data, 'id')) ? $data->id : ""; - $this->user->profile->firstName = (property_exists($data, 'first_name')) ? $data->first_name : ""; - $this->user->profile->lastName = (property_exists($data, 'last_name')) ? $data->last_name : ""; - $this->user->profile->displayName = (property_exists($data, 'name')) ? trim($data->name) : ""; - $this->user->profile->gender = (property_exists($data, 'gender')) ? $data->gender : ""; - - //wl.basic - $this->user->profile->profileURL = (property_exists($data, 'link')) ? $data->link : ""; - - //wl.emails - $this->user->profile->email = (property_exists($data, 'emails')) ? $data->emails->preferred : ""; - $this->user->profile->emailVerified = (property_exists($data, 'emails')) ? $data->emails->account : ""; - - //wl.birthday - $this->user->profile->birthDay = (property_exists($data, 'birth_day')) ? $data->birth_day : ""; - $this->user->profile->birthMonth = (property_exists($data, 'birth_month')) ? $data->birth_month : ""; - $this->user->profile->birthYear = (property_exists($data, 'birth_year')) ? $data->birth_year : ""; - - return $this->user->profile; - } - - /** - * Windows Live api does not support retrieval of email addresses (only hashes :/) - * {@inheritdoc} - */ - function getUserContacts() { - $response = $this->api->get('me/contacts'); - - if ($this->api->http_code != 200) { - throw new Exception('User contacts request failed! ' . $this->providerId . ' returned an error: ' . $this->errorMessageByStatus($this->api->http_code)); - } - - if (!isset($response->data) || ( isset($response->errcode) && $response->errcode != 0 )) { - return array(); - } - - $contacts = array(); - - foreach ($response->data as $item) { - $uc = new Hybrid_User_Contact(); - - $uc->identifier = (property_exists($item, 'id')) ? $item->id : ""; - $uc->displayName = (property_exists($item, 'name')) ? $item->name : ""; - $uc->email = (property_exists($item, 'emails')) ? $item->emails->preferred : ""; - $contacts[] = $uc; - } - - return $contacts; - } - -} + + * @version 0.2 + * @license BSD License + */ + +/** + * Hybrid_Providers_Live - Windows Live provider adapter based on OAuth2 protocol + */ +class Hybrid_Providers_Live extends Hybrid_Provider_Model_OAuth2 { + + /** + * {@inheritdoc} + */ + public $scope = 'wl.basic wl.contacts_emails wl.emails wl.signin wl.share wl.birthday'; + + /** + * {@inheritdoc} + */ + function initialize() { + parent::initialize(); + + // Provider api end-points + $this->api->api_base_url = 'https://apis.live.net/v5.0/'; + $this->api->authorize_url = 'https://login.live.com/oauth20_authorize.srf'; + $this->api->token_url = 'https://login.live.com/oauth20_token.srf'; + } + + /** + * {@inheritdoc} + */ + function getUserProfile() { + $data = $this->api->get("me"); + + if (!isset($data->id)) { + throw new Exception("User profile request failed! {$this->providerId} returned an invalid response: " . Hybrid_Logger::dumpData( $data ), 6); + } + + $this->user->profile->identifier = (property_exists($data, 'id')) ? $data->id : ""; + $this->user->profile->firstName = (property_exists($data, 'first_name')) ? $data->first_name : ""; + $this->user->profile->lastName = (property_exists($data, 'last_name')) ? $data->last_name : ""; + $this->user->profile->displayName = (property_exists($data, 'name')) ? trim($data->name) : ""; + $this->user->profile->gender = (property_exists($data, 'gender')) ? $data->gender : ""; + + //wl.basic + $this->user->profile->profileURL = (property_exists($data, 'link')) ? $data->link : ""; + + //wl.emails + $this->user->profile->email = (property_exists($data, 'emails')) ? $data->emails->preferred : ""; + $this->user->profile->emailVerified = (property_exists($data, 'emails')) ? $data->emails->account : ""; + + //wl.birthday + $this->user->profile->birthDay = (property_exists($data, 'birth_day')) ? $data->birth_day : ""; + $this->user->profile->birthMonth = (property_exists($data, 'birth_month')) ? $data->birth_month : ""; + $this->user->profile->birthYear = (property_exists($data, 'birth_year')) ? $data->birth_year : ""; + + return $this->user->profile; + } + + /** + * Windows Live api does not support retrieval of email addresses (only hashes :/) + * {@inheritdoc} + */ + function getUserContacts() { + $response = $this->api->get('me/contacts'); + + if ($this->api->http_code != 200) { + throw new Exception('User contacts request failed! ' . $this->providerId . ' returned an error: ' . $this->errorMessageByStatus($this->api->http_code)); + } + + if (!isset($response->data) || ( isset($response->errcode) && $response->errcode != 0 )) { + return array(); + } + + $contacts = array(); + + foreach ($response->data as $item) { + $uc = new Hybrid_User_Contact(); + + $uc->identifier = (property_exists($item, 'id')) ? $item->id : ""; + $uc->displayName = (property_exists($item, 'name')) ? $item->name : ""; + $uc->email = (property_exists($item, 'emails')) ? $item->emails->preferred : ""; + $contacts[] = $uc; + } + + return $contacts; + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Providers/MySpace.php b/e107_handlers/hybridauth/Hybrid/Providers/MySpace.php index 619ce08b5..8ce0ffe35 100644 --- a/e107_handlers/hybridauth/Hybrid/Providers/MySpace.php +++ b/e107_handlers/hybridauth/Hybrid/Providers/MySpace.php @@ -1,164 +1,164 @@ -api->api_endpoint_url = "http://api.myspace.com/v1/"; - $this->api->authorize_url = "http://api.myspace.com/authorize"; - $this->api->request_token_url = "http://api.myspace.com/request_token"; - $this->api->access_token_url = "http://api.myspace.com/access_token"; - } - - /** - * get the connected uid from myspace api - */ - public function getCurrentUserId() - { - $response = $this->api->get( 'http://api.myspace.com/v1/user.json' ); - - if ( ! isset( $response->userId ) ){ - throw new Exception( "User id request failed! {$this->providerId} returned an invalid response." ); - } - - return $response->userId; - } - - /** - * load the user profile from the IDp api client - */ - function getUserProfile() - { - $userId = $this->getCurrentUserId(); - - $data = $this->api->get( 'http://api.myspace.com/v1/users/' . $userId . '/profile.json' ); - - if ( ! is_object( $data ) ){ - throw new Exception( "User profile request failed! {$this->providerId} returned an invalid response.", 6 ); - } - - $this->user->profile->identifier = $userId; - $this->user->profile->displayName = $data->basicprofile->name; - $this->user->profile->description = $data->aboutme; - $this->user->profile->gender = $data->basicprofile->gender; - $this->user->profile->photoURL = $data->basicprofile->image; - $this->user->profile->profileURL = $data->basicprofile->webUri; - $this->user->profile->age = $data->age; - $this->user->profile->country = $data->country; - $this->user->profile->region = $data->region; - $this->user->profile->city = $data->city; - $this->user->profile->zip = $data->postalcode; - - return $this->user->profile; - } - - /** - * load the user contacts - */ - function getUserContacts() - { - $userId = $this->getCurrentUserId(); - - $response = $this->api->get( "http://api.myspace.com/v1/users/" . $userId . "/friends.json" ); - - if ( ! is_object( $response ) ){ - throw new Exception( "User profile request failed! {$this->providerId} returned an invalid response.", 6 ); - } - - $contacts = ARRAY(); - - foreach( $response->Friends as $item ){ - $uc = new Hybrid_User_Contact(); - - $uc->identifier = $item->userId; - $uc->displayName = $item->name; - $uc->profileURL = $item->webUri; - $uc->photoURL = $item->image; - $uc->description = $item->status; - - $contacts[] = $uc; - } - - return $contacts; - } - - /** - * update user status - */ - function setUserStatus( $status ) - { - // crappy myspace... gonna see this asaic - $userId = $this->getCurrentUserId(); - - $parameters = array( 'status' => $status ); - - $response = $this->api->api( "http://api.myspace.com/v1/users/" . $userId . "/status", 'PUT', $parameters ); - - // check the last HTTP status code returned - if ( $this->api->http_code != 200 ) - { - throw new Exception( "Update user status failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus( $this->api->http_code ) ); - } - } - - /** - * load the user latest activity - * - timeline : all the stream - * - me : the user activity only - */ - function getUserActivity( $stream ) - { - $userId = $this->getCurrentUserId(); - - if( $stream == "me" ){ - $response = $this->api->get( "http://api.myspace.com/v1/users/" . $userId . "/status.json" ); - } - else{ - $response = $this->api->get( "http://api.myspace.com/v1/users/" . $userId . "/friends/status.json" ); - } - - if ( ! is_object( $response ) ){ - throw new Exception( "User profile request failed! {$this->providerId} returned an invalid response.", 6 ); - } - - $activities = ARRAY(); - - if( $stream == "me" ){ - // todo - } - else{ - foreach( $response->FriendsStatus as $item ){ - $ua = new Hybrid_User_Activity(); - - $ua->id = $item->statusId; - $ua->date = NULL; // to find out!! - $ua->text = $item->status; - - $ua->user->identifier = $item->user->userId; - $ua->user->displayName = $item->user->name; - $ua->user->profileURL = $item->user->uri; - $ua->user->photoURL = $item->user->image; - - $activities[] = $ua; - } - } - - return $activities; - } -} +api->api_endpoint_url = "http://api.myspace.com/v1/"; + $this->api->authorize_url = "http://api.myspace.com/authorize"; + $this->api->request_token_url = "http://api.myspace.com/request_token"; + $this->api->access_token_url = "http://api.myspace.com/access_token"; + } + + /** + * get the connected uid from myspace api + */ + public function getCurrentUserId() + { + $response = $this->api->get( 'http://api.myspace.com/v1/user.json' ); + + if ( ! isset( $response->userId ) ){ + throw new Exception( "User id request failed! {$this->providerId} returned an invalid response." ); + } + + return $response->userId; + } + + /** + * load the user profile from the IDp api client + */ + function getUserProfile() + { + $userId = $this->getCurrentUserId(); + + $data = $this->api->get( 'http://api.myspace.com/v1/users/' . $userId . '/profile.json' ); + + if ( ! is_object( $data ) ){ + throw new Exception( "User profile request failed! {$this->providerId} returned an invalid response.", 6 ); + } + + $this->user->profile->identifier = $userId; + $this->user->profile->displayName = $data->basicprofile->name; + $this->user->profile->description = $data->aboutme; + $this->user->profile->gender = $data->basicprofile->gender; + $this->user->profile->photoURL = $data->basicprofile->image; + $this->user->profile->profileURL = $data->basicprofile->webUri; + $this->user->profile->age = $data->age; + $this->user->profile->country = $data->country; + $this->user->profile->region = $data->region; + $this->user->profile->city = $data->city; + $this->user->profile->zip = $data->postalcode; + + return $this->user->profile; + } + + /** + * load the user contacts + */ + function getUserContacts() + { + $userId = $this->getCurrentUserId(); + + $response = $this->api->get( "http://api.myspace.com/v1/users/" . $userId . "/friends.json" ); + + if ( ! is_object( $response ) ){ + throw new Exception( "User profile request failed! {$this->providerId} returned an invalid response.", 6 ); + } + + $contacts = ARRAY(); + + foreach( $response->Friends as $item ){ + $uc = new Hybrid_User_Contact(); + + $uc->identifier = $item->userId; + $uc->displayName = $item->name; + $uc->profileURL = $item->webUri; + $uc->photoURL = $item->image; + $uc->description = $item->status; + + $contacts[] = $uc; + } + + return $contacts; + } + + /** + * update user status + */ + function setUserStatus( $status ) + { + // crappy myspace... gonna see this asaic + $userId = $this->getCurrentUserId(); + + $parameters = array( 'status' => $status ); + + $response = $this->api->api( "http://api.myspace.com/v1/users/" . $userId . "/status", 'PUT', $parameters ); + + // check the last HTTP status code returned + if ( $this->api->http_code != 200 ) + { + throw new Exception( "Update user status failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus( $this->api->http_code ) ); + } + } + + /** + * load the user latest activity + * - timeline : all the stream + * - me : the user activity only + */ + function getUserActivity( $stream ) + { + $userId = $this->getCurrentUserId(); + + if( $stream == "me" ){ + $response = $this->api->get( "http://api.myspace.com/v1/users/" . $userId . "/status.json" ); + } + else{ + $response = $this->api->get( "http://api.myspace.com/v1/users/" . $userId . "/friends/status.json" ); + } + + if ( ! is_object( $response ) ){ + throw new Exception( "User profile request failed! {$this->providerId} returned an invalid response.", 6 ); + } + + $activities = ARRAY(); + + if( $stream == "me" ){ + // todo + } + else{ + foreach( $response->FriendsStatus as $item ){ + $ua = new Hybrid_User_Activity(); + + $ua->id = $item->statusId; + $ua->date = NULL; // to find out!! + $ua->text = $item->status; + + $ua->user->identifier = $item->user->userId; + $ua->user->displayName = $item->user->name; + $ua->user->profileURL = $item->user->uri; + $ua->user->photoURL = $item->user->image; + + $activities[] = $ua; + } + } + + return $activities; + } +} diff --git a/e107_handlers/hybridauth/Hybrid/Providers/OpenID.php b/e107_handlers/hybridauth/Hybrid/Providers/OpenID.php index 8f7903c78..61e71e560 100644 --- a/e107_handlers/hybridauth/Hybrid/Providers/OpenID.php +++ b/e107_handlers/hybridauth/Hybrid/Providers/OpenID.php @@ -1,16 +1,16 @@ -api->api_base_url = "https://api.twitter.com/1.1/"; - $this->api->authorize_url = "https://api.twitter.com/oauth/authenticate"; - $this->api->request_token_url = "https://api.twitter.com/oauth/request_token"; - $this->api->access_token_url = "https://api.twitter.com/oauth/access_token"; - - if (isset($this->config['api_version']) && $this->config['api_version']) { - $this->api->api_base_url = "https://api.twitter.com/{$this->config['api_version']}/"; - } - - if (isset($this->config['authorize']) && $this->config['authorize']) { - $this->api->authorize_url = "https://api.twitter.com/oauth/authorize"; - } - - $this->api->curl_auth_header = false; - } - - /** - * {@inheritdoc} - */ - function loginBegin() { - // Initiate the Reverse Auth flow; cf. https://dev.twitter.com/docs/ios/using-reverse-auth - if (isset($_REQUEST['reverse_auth']) && ($_REQUEST['reverse_auth'] == 'yes')) { - $stage1 = $this->api->signedRequest($this->api->request_token_url, 'POST', array('x_auth_mode' => 'reverse_auth')); - if ($this->api->http_code != 200) { - throw new Exception("Authentication failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code), 5); - } - $responseObj = array('x_reverse_auth_parameters' => $stage1, 'x_reverse_auth_target' => $this->config["keys"]["key"]); - $response = json_encode($responseObj); - header("Content-Type: application/json", true, 200); - echo $response; - die(); - } - $tokens = $this->api->requestToken($this->endpoint); - - // request tokens as received from provider - $this->request_tokens_raw = $tokens; - - // check the last HTTP status code returned - if ($this->api->http_code != 200) { - throw new Exception("Authentication failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code), 5); - } - - if (!isset($tokens["oauth_token"])) { - throw new Exception("Authentication failed! {$this->providerId} returned an invalid oauth token.", 5); - } - - $this->token("request_token", $tokens["oauth_token"]); - $this->token("request_token_secret", $tokens["oauth_token_secret"]); - - // redirect the user to the provider authentication url with force_login - if (( isset($this->config['force_login']) && $this->config['force_login'] ) || ( isset($this->config['force']) && $this->config['force'] === true )) { - Hybrid_Auth::redirect($this->api->authorizeUrl($tokens, array('force_login' => true))); - } - - // else, redirect the user to the provider authentication url - Hybrid_Auth::redirect($this->api->authorizeUrl($tokens)); - } - - /** - * {@inheritdoc} - */ - function loginFinish() { - // in case we are completing a Reverse Auth flow; cf. https://dev.twitter.com/docs/ios/using-reverse-auth - if (isset($_REQUEST['oauth_token_secret'])) { - $tokens = $_REQUEST; - $this->access_tokens_raw = $tokens; - - // we should have an access_token unless something has gone wrong - if (!isset($tokens["oauth_token"])) { - throw new Exception("Authentication failed! {$this->providerId} returned an invalid access token.", 5); - } - - // Get rid of tokens we don't need - $this->deleteToken("request_token"); - $this->deleteToken("request_token_secret"); - - // Store access_token and secret for later use - $this->token("access_token", $tokens['oauth_token']); - $this->token("access_token_secret", $tokens['oauth_token_secret']); - - // set user as logged in to the current provider - $this->setUserConnected(); - return; - } - parent::loginFinish(); - } - - /** - * {@inheritdoc} - */ - function getUserProfile() { - $includeEmail = isset($this->config['includeEmail']) ? (bool) $this->config['includeEmail'] : false; - $response = $this->api->get('account/verify_credentials.json'. ($includeEmail ? '?include_email=true' : '')); - - // check the last HTTP status code returned - if ($this->api->http_code != 200) { - throw new Exception("User profile request failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code), 6); - } - - if (!is_object($response) || !isset($response->id)) { - throw new Exception("User profile request failed! {$this->providerId} api returned an invalid response: " . Hybrid_Logger::dumpData( $response ), 6); - } - - # store the user profile. - $this->user->profile->identifier = (property_exists($response, 'id')) ? $response->id : ""; - $this->user->profile->displayName = (property_exists($response, 'screen_name')) ? $response->screen_name : ""; - $this->user->profile->description = (property_exists($response, 'description')) ? $response->description : ""; - $this->user->profile->firstName = (property_exists($response, 'name')) ? $response->name : ""; - $this->user->profile->photoURL = (property_exists($response, 'profile_image_url')) ? (str_replace('_normal', '', $response->profile_image_url)) : ""; - $this->user->profile->profileURL = (property_exists($response, 'screen_name')) ? ("http://twitter.com/" . $response->screen_name) : ""; - $this->user->profile->webSiteURL = (property_exists($response, 'url')) ? $response->url : ""; - $this->user->profile->region = (property_exists($response, 'location')) ? $response->location : ""; - if($includeEmail) $this->user->profile->email = (property_exists($response, 'email')) ? $response->email : ""; - if($includeEmail) $this->user->profile->emailVerified = (property_exists($response, 'email')) ? $response->email : ""; - - return $this->user->profile; - } - - /** - * {@inheritdoc} - */ - function getUserContacts() { - $parameters = array('cursor' => '-1'); - $response = $this->api->get('friends/ids.json', $parameters); - - // check the last HTTP status code returned - if ($this->api->http_code != 200) { - throw new Exception("User contacts request failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code)); - } - - if (!$response || !count($response->ids)) { - return array(); - } - - // 75 id per time should be okey - $contactsids = array_chunk($response->ids, 75); - - $contacts = array(); - - foreach ($contactsids as $chunk) { - $parameters = array('user_id' => implode(",", $chunk)); - $response = $this->api->get('users/lookup.json', $parameters); - - // check the last HTTP status code returned - if ($this->api->http_code != 200) { - throw new Exception("User contacts request failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code)); - } - - if ($response && count($response)) { - foreach ($response as $item) { - $uc = new Hybrid_User_Contact(); - - $uc->identifier = (property_exists($item, 'id')) ? $item->id : ""; - $uc->displayName = (property_exists($item, 'name')) ? $item->name : ""; - $uc->profileURL = (property_exists($item, 'screen_name')) ? ("http://twitter.com/" . $item->screen_name) : ""; - $uc->photoURL = (property_exists($item, 'profile_image_url')) ? $item->profile_image_url : ""; - $uc->description = (property_exists($item, 'description')) ? $item->description : ""; - - $contacts[] = $uc; - } - } - } - - return $contacts; - } - - /** - * {@inheritdoc} - */ - function setUserStatus($status) { - - if (is_array($status) && isset($status['message']) && isset($status['picture'])) { - $response = $this->api->post('statuses/update_with_media.json', array('status' => $status['message'], 'media[]' => file_get_contents($status['picture'])), null, null, true); - } else { - $response = $this->api->post('statuses/update.json', array('status' => $status)); - } - - // check the last HTTP status code returned - if ($this->api->http_code != 200) { - throw new Exception("Update user status failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code)); - } - - return $response; - } - - /** - * {@inheritdoc} - */ - function getUserStatus($tweetid) { - $info = $this->api->get('statuses/show.json?id=' . $tweetid . '&include_entities=true'); - - // check the last HTTP status code returned - if ($this->api->http_code != 200 || !isset($info->id)) { - throw new Exception("Cannot retrieve user status! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code)); - } - - return $info; - } - - /** - * load the user latest activity - * - timeline : all the stream - * - me : the user activity only - * - * by default return the timeline - * {@inheritdoc} - */ - function getUserActivity($stream) { - if ($stream == "me") { - $response = $this->api->get('statuses/user_timeline.json'); - } else { - $response = $this->api->get('statuses/home_timeline.json'); - } - - // check the last HTTP status code returned - if ($this->api->http_code != 200) { - throw new Exception("User activity stream request failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code)); - } - - if (!$response) { - return array(); - } - - $activities = array(); - - foreach ($response as $item) { - $ua = new Hybrid_User_Activity(); - - $ua->id = (property_exists($item, 'id')) ? $item->id : ""; - $ua->date = (property_exists($item, 'created_at')) ? strtotime($item->created_at) : ""; - $ua->text = (property_exists($item, 'text')) ? $item->text : ""; - - $ua->user->identifier = (property_exists($item->user, 'id')) ? $item->user->id : ""; - $ua->user->displayName = (property_exists($item->user, 'name')) ? $item->user->name : ""; - $ua->user->profileURL = (property_exists($item->user, 'screen_name')) ? ("http://twitter.com/" . $item->user->screen_name) : ""; - $ua->user->photoURL = (property_exists($item->user, 'profile_image_url')) ? $item->user->profile_image_url : ""; - - $activities[] = $ua; - } - - return $activities; - } - -} +api->api_base_url = "https://api.twitter.com/1.1/"; + $this->api->authorize_url = "https://api.twitter.com/oauth/authenticate"; + $this->api->request_token_url = "https://api.twitter.com/oauth/request_token"; + $this->api->access_token_url = "https://api.twitter.com/oauth/access_token"; + + if (isset($this->config['api_version']) && $this->config['api_version']) { + $this->api->api_base_url = "https://api.twitter.com/{$this->config['api_version']}/"; + } + + if (isset($this->config['authorize']) && $this->config['authorize']) { + $this->api->authorize_url = "https://api.twitter.com/oauth/authorize"; + } + + $this->api->curl_auth_header = false; + } + + /** + * {@inheritdoc} + */ + function loginBegin() { + // Initiate the Reverse Auth flow; cf. https://dev.twitter.com/docs/ios/using-reverse-auth + if (isset($_REQUEST['reverse_auth']) && ($_REQUEST['reverse_auth'] == 'yes')) { + $stage1 = $this->api->signedRequest($this->api->request_token_url, 'POST', array('x_auth_mode' => 'reverse_auth')); + if ($this->api->http_code != 200) { + throw new Exception("Authentication failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code), 5); + } + $responseObj = array('x_reverse_auth_parameters' => $stage1, 'x_reverse_auth_target' => $this->config["keys"]["key"]); + $response = json_encode($responseObj); + header("Content-Type: application/json", true, 200); + echo $response; + die(); + } + $tokens = $this->api->requestToken($this->endpoint); + + // request tokens as received from provider + $this->request_tokens_raw = $tokens; + + // check the last HTTP status code returned + if ($this->api->http_code != 200) { + throw new Exception("Authentication failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code), 5); + } + + if (!isset($tokens["oauth_token"])) { + throw new Exception("Authentication failed! {$this->providerId} returned an invalid oauth token.", 5); + } + + $this->token("request_token", $tokens["oauth_token"]); + $this->token("request_token_secret", $tokens["oauth_token_secret"]); + + // redirect the user to the provider authentication url with force_login + if (( isset($this->config['force_login']) && $this->config['force_login'] ) || ( isset($this->config['force']) && $this->config['force'] === true )) { + Hybrid_Auth::redirect($this->api->authorizeUrl($tokens, array('force_login' => true))); + } + + // else, redirect the user to the provider authentication url + Hybrid_Auth::redirect($this->api->authorizeUrl($tokens)); + } + + /** + * {@inheritdoc} + */ + function loginFinish() { + // in case we are completing a Reverse Auth flow; cf. https://dev.twitter.com/docs/ios/using-reverse-auth + if (isset($_REQUEST['oauth_token_secret'])) { + $tokens = $_REQUEST; + $this->access_tokens_raw = $tokens; + + // we should have an access_token unless something has gone wrong + if (!isset($tokens["oauth_token"])) { + throw new Exception("Authentication failed! {$this->providerId} returned an invalid access token.", 5); + } + + // Get rid of tokens we don't need + $this->deleteToken("request_token"); + $this->deleteToken("request_token_secret"); + + // Store access_token and secret for later use + $this->token("access_token", $tokens['oauth_token']); + $this->token("access_token_secret", $tokens['oauth_token_secret']); + + // set user as logged in to the current provider + $this->setUserConnected(); + return; + } + parent::loginFinish(); + } + + /** + * {@inheritdoc} + */ + function getUserProfile() { + $includeEmail = isset($this->config['includeEmail']) ? (bool) $this->config['includeEmail'] : false; + $response = $this->api->get('account/verify_credentials.json'. ($includeEmail ? '?include_email=true' : '')); + + // check the last HTTP status code returned + if ($this->api->http_code != 200) { + throw new Exception("User profile request failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code), 6); + } + + if (!is_object($response) || !isset($response->id)) { + throw new Exception("User profile request failed! {$this->providerId} api returned an invalid response: " . Hybrid_Logger::dumpData( $response ), 6); + } + + # store the user profile. + $this->user->profile->identifier = (property_exists($response, 'id')) ? $response->id : ""; + $this->user->profile->displayName = (property_exists($response, 'screen_name')) ? $response->screen_name : ""; + $this->user->profile->description = (property_exists($response, 'description')) ? $response->description : ""; + $this->user->profile->firstName = (property_exists($response, 'name')) ? $response->name : ""; + $this->user->profile->photoURL = (property_exists($response, 'profile_image_url')) ? (str_replace('_normal', '', $response->profile_image_url)) : ""; + $this->user->profile->profileURL = (property_exists($response, 'screen_name')) ? ("http://twitter.com/" . $response->screen_name) : ""; + $this->user->profile->webSiteURL = (property_exists($response, 'url')) ? $response->url : ""; + $this->user->profile->region = (property_exists($response, 'location')) ? $response->location : ""; + if($includeEmail) $this->user->profile->email = (property_exists($response, 'email')) ? $response->email : ""; + if($includeEmail) $this->user->profile->emailVerified = (property_exists($response, 'email')) ? $response->email : ""; + + return $this->user->profile; + } + + /** + * {@inheritdoc} + */ + function getUserContacts() { + $parameters = array('cursor' => '-1'); + $response = $this->api->get('friends/ids.json', $parameters); + + // check the last HTTP status code returned + if ($this->api->http_code != 200) { + throw new Exception("User contacts request failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code)); + } + + if (!$response || !count($response->ids)) { + return array(); + } + + // 75 id per time should be okey + $contactsids = array_chunk($response->ids, 75); + + $contacts = array(); + + foreach ($contactsids as $chunk) { + $parameters = array('user_id' => implode(",", $chunk)); + $response = $this->api->get('users/lookup.json', $parameters); + + // check the last HTTP status code returned + if ($this->api->http_code != 200) { + throw new Exception("User contacts request failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code)); + } + + if ($response && count($response)) { + foreach ($response as $item) { + $uc = new Hybrid_User_Contact(); + + $uc->identifier = (property_exists($item, 'id')) ? $item->id : ""; + $uc->displayName = (property_exists($item, 'name')) ? $item->name : ""; + $uc->profileURL = (property_exists($item, 'screen_name')) ? ("http://twitter.com/" . $item->screen_name) : ""; + $uc->photoURL = (property_exists($item, 'profile_image_url')) ? $item->profile_image_url : ""; + $uc->description = (property_exists($item, 'description')) ? $item->description : ""; + + $contacts[] = $uc; + } + } + } + + return $contacts; + } + + /** + * {@inheritdoc} + */ + function setUserStatus($status) { + + if (is_array($status) && isset($status['message']) && isset($status['picture'])) { + $response = $this->api->post('statuses/update_with_media.json', array('status' => $status['message'], 'media[]' => file_get_contents($status['picture'])), null, null, true); + } else { + $response = $this->api->post('statuses/update.json', array('status' => $status)); + } + + // check the last HTTP status code returned + if ($this->api->http_code != 200) { + throw new Exception("Update user status failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code)); + } + + return $response; + } + + /** + * {@inheritdoc} + */ + function getUserStatus($tweetid) { + $info = $this->api->get('statuses/show.json?id=' . $tweetid . '&include_entities=true'); + + // check the last HTTP status code returned + if ($this->api->http_code != 200 || !isset($info->id)) { + throw new Exception("Cannot retrieve user status! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code)); + } + + return $info; + } + + /** + * load the user latest activity + * - timeline : all the stream + * - me : the user activity only + * + * by default return the timeline + * {@inheritdoc} + */ + function getUserActivity($stream) { + if ($stream == "me") { + $response = $this->api->get('statuses/user_timeline.json'); + } else { + $response = $this->api->get('statuses/home_timeline.json'); + } + + // check the last HTTP status code returned + if ($this->api->http_code != 200) { + throw new Exception("User activity stream request failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus($this->api->http_code)); + } + + if (!$response) { + return array(); + } + + $activities = array(); + + foreach ($response as $item) { + $ua = new Hybrid_User_Activity(); + + $ua->id = (property_exists($item, 'id')) ? $item->id : ""; + $ua->date = (property_exists($item, 'created_at')) ? strtotime($item->created_at) : ""; + $ua->text = (property_exists($item, 'text')) ? $item->text : ""; + + $ua->user->identifier = (property_exists($item->user, 'id')) ? $item->user->id : ""; + $ua->user->displayName = (property_exists($item->user, 'name')) ? $item->user->name : ""; + $ua->user->profileURL = (property_exists($item->user, 'screen_name')) ? ("http://twitter.com/" . $item->user->screen_name) : ""; + $ua->user->photoURL = (property_exists($item->user, 'profile_image_url')) ? $item->user->profile_image_url : ""; + + $activities[] = $ua; + } + + return $activities; + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Providers/Yahoo.php b/e107_handlers/hybridauth/Hybrid/Providers/Yahoo.php index 81c48285f..44534244a 100644 --- a/e107_handlers/hybridauth/Hybrid/Providers/Yahoo.php +++ b/e107_handlers/hybridauth/Hybrid/Providers/Yahoo.php @@ -1,269 +1,269 @@ - - * @author Oleg Kuzava - * @version 1.0 - * @license BSD License - */ - -/** - * Hybrid_Providers_Yahoo - Yahoo provider adapter based on OAuth2 protocol. - */ -class Hybrid_Providers_Yahoo extends Hybrid_Provider_Model_OAuth2 { - - /** - * Define Yahoo scopes. - * - * @var array $scope - * If empty will be used YDN App scopes. - * @see https://developer.yahoo.com/oauth2/guide/yahoo_scopes. - */ - public $scope = []; - - /** - * {@inheritdoc} - */ - function initialize() { - parent::initialize(); - - // Provider api end-points. - $this->api->api_base_url = "https://social.yahooapis.com/v1/"; - $this->api->authorize_url = "https://api.login.yahoo.com/oauth2/request_auth"; - $this->api->token_url = "https://api.login.yahoo.com/oauth2/get_token"; - - // Set token headers. - $this->setAuthorizationHeaders("basic"); - } - - /** - * {@inheritdoc} - */ - function loginBegin() { - if (is_array($this->scope)) { - $this->scope = implode(",", $this->scope); - } - parent::loginBegin(); - } - - /** - * {@inheritdoc} - */ - function getUserProfile() { - $userId = $this->getCurrentUserId(); - - $response = $this->api->get("user/{$userId}/profile", array( - "format" => "json", - )); - - if (!isset($response->profile)) { - throw new Exception("User profile request failed! {$this->providerId} returned an invalid response: " . Hybrid_Logger::dumpData($response), 6); - } - - $data = $response->profile; - - $this->user->profile->identifier = isset($data->guid) ? $data->guid : ""; - $this->user->profile->firstName = isset($data->givenName) ? $data->givenName : ""; - $this->user->profile->lastName = isset($data->familyName) ? $data->familyName : ""; - $this->user->profile->displayName = isset($data->nickname) ? trim($data->nickname) : ""; - $this->user->profile->profileURL = isset($data->profileUrl) ? $data->profileUrl : ""; - $this->user->profile->gender = isset($data->gender) ? $data->gender : ""; - - if ($this->user->profile->gender === "F") { - $this->user->profile->gender = "female"; - } - elseif ($this->user->profile->gender === "M") { - $this->user->profile->gender = "male"; - } - - if (isset($data->emails)) { - $email = ""; - foreach ($data->emails as $v) { - if (isset($v->primary) && $v->primary) { - $email = isset($v->handle) ? $v->handle : ""; - break; - } - } - $this->user->profile->email = $email; - $this->user->profile->emailVerified = $email; - } - - $this->user->profile->age = isset($data->displayAge) ? $data->displayAge : ""; - $this->user->profile->photoURL = isset($data->image) ? $data->image->imageUrl : ""; - - $this->user->profile->address = isset($data->location) ? $data->location : ""; - $this->user->profile->language = isset($data->lang) ? $data->lang : ""; - - return $this->user->profile; - } - - /** - * {@inheritdoc} - */ - function getUserContacts() { - $userId = $this->getCurrentUserId(); - - $response = $this->api->get("user/{$userId}/contacts", array( - "format" => "json", - "count" => "max", - )); - - if ($this->api->http_code != 200) { - throw new Exception("User contacts request failed! {$this->providerId} returned an error: " . $this->errorMessageByStatus()); - } - - if (!isset($response->contacts) || !isset($response->contacts->contact) || (isset($response->errcode) && $response->errcode != 0)) { - return array(); - } - - $contacts = array(); - foreach ($response->contacts->contact as $item) { - $uc = new Hybrid_User_Contact(); - - $uc->identifier = isset($item->id) ? $item->id : ""; - $uc->email = $this->selectEmail($item->fields); - $uc->displayName = $this->selectName($item->fields); - $uc->photoURL = $this->selectPhoto($item->fields); - - $contacts[] = $uc; - } - - return $contacts; - } - - /** - * Returns current user id. - * - * @return string - * Current user ID. - * @throws Exception - */ - function getCurrentUserId() { - // Set headers to get refresh token. - $this->setAuthorizationHeaders("basic"); - - // Refresh tokens if needed. - $this->refreshToken(); - - // Set headers to make api call. - $this->setAuthorizationHeaders("bearer"); - - $response = $this->api->get("me/guid", array( - "format" => "json", - )); - - if (!isset($response->guid->value)) { - throw new Exception("User id request failed! {$this->providerId} returned an invalid response: " . Hybrid_Logger::dumpData($response)); - } - - return $response->guid->value; - } - - /** - * Utility function for returning values from XML-like objects. - * - * @param stdClass $vs - * Object. - * @param string $t - * Property name. - * @return mixed - */ - private function select($vs, $t) { - foreach ($vs as $v) { - if ($v->type == $t) { - return $v; - } - } - - return null; - } - - /** - * Parses user name. - * - * @param stdClass $v - * Object. - * @return string - * User name. - */ - private function selectName($v) { - $s = $this->select($v, "name"); - if (!$s) { - $s = $this->select($v, "nickname"); - return isset($s->value) ? $s->value : ""; - } - return isset($s->value) ? "{$s->value->givenName} {$s->value->familyName}" : ""; - } - - /** - * Parses photo URL. - * - * @param stdClass $v - * Object. - * @return string - * Photo URL. - */ - private function selectPhoto($v) { - $s = $this->select($v, "image"); - - return isset($s->value) ? $s->value->imageUrl : ""; - } - - /** - * Parses email. - * - * @param stdClass $v - * Object - * @return string - * An email address. - */ - private function selectEmail($v) { - $s = $this->select($v, "email"); - if (empty($s)) { - $s = $this->select($v, "yahooid"); - if (isset($s->value) && strpos($s->value, "@") === FALSE) { - $s->value .= "@yahoo.com"; - } - } - - return isset($s->value) ? $s->value : ""; - } - - /** - * Set correct Authorization headers. - * - * @param string $token_type - * Specify token type. - * - * @return void - */ - private function setAuthorizationHeaders($token_type) { - switch ($token_type) { - case "basic": - // The /get_token requires authorization header. - $token = base64_encode("{$this->config["keys"]["id"]}:{$this->config["keys"]["secret"]}"); - $this->api->curl_header = array( - "Authorization: Basic {$token}", - "Content-Type: application/x-www-form-urlencoded", - ); - break; - - case "bearer": - // Yahoo API requires the token to be passed as a Bearer within the authorization header. - $this->api->curl_header = array( - "Authorization: Bearer {$this->api->access_token}", - ); - break; - } - } - -} + + * @author Oleg Kuzava + * @version 1.0 + * @license BSD License + */ + +/** + * Hybrid_Providers_Yahoo - Yahoo provider adapter based on OAuth2 protocol. + */ +class Hybrid_Providers_Yahoo extends Hybrid_Provider_Model_OAuth2 { + + /** + * Define Yahoo scopes. + * + * @var array $scope + * If empty will be used YDN App scopes. + * @see https://developer.yahoo.com/oauth2/guide/yahoo_scopes. + */ + public $scope = []; + + /** + * {@inheritdoc} + */ + function initialize() { + parent::initialize(); + + // Provider api end-points. + $this->api->api_base_url = "https://social.yahooapis.com/v1/"; + $this->api->authorize_url = "https://api.login.yahoo.com/oauth2/request_auth"; + $this->api->token_url = "https://api.login.yahoo.com/oauth2/get_token"; + + // Set token headers. + $this->setAuthorizationHeaders("basic"); + } + + /** + * {@inheritdoc} + */ + function loginBegin() { + if (is_array($this->scope)) { + $this->scope = implode(",", $this->scope); + } + parent::loginBegin(); + } + + /** + * {@inheritdoc} + */ + function getUserProfile() { + $userId = $this->getCurrentUserId(); + + $response = $this->api->get("user/{$userId}/profile", array( + "format" => "json", + )); + + if (!isset($response->profile)) { + throw new Exception("User profile request failed! {$this->providerId} returned an invalid response: " . Hybrid_Logger::dumpData($response), 6); + } + + $data = $response->profile; + + $this->user->profile->identifier = isset($data->guid) ? $data->guid : ""; + $this->user->profile->firstName = isset($data->givenName) ? $data->givenName : ""; + $this->user->profile->lastName = isset($data->familyName) ? $data->familyName : ""; + $this->user->profile->displayName = isset($data->nickname) ? trim($data->nickname) : ""; + $this->user->profile->profileURL = isset($data->profileUrl) ? $data->profileUrl : ""; + $this->user->profile->gender = isset($data->gender) ? $data->gender : ""; + + if ($this->user->profile->gender === "F") { + $this->user->profile->gender = "female"; + } + elseif ($this->user->profile->gender === "M") { + $this->user->profile->gender = "male"; + } + + if (isset($data->emails)) { + $email = ""; + foreach ($data->emails as $v) { + if (isset($v->primary) && $v->primary) { + $email = isset($v->handle) ? $v->handle : ""; + break; + } + } + $this->user->profile->email = $email; + $this->user->profile->emailVerified = $email; + } + + $this->user->profile->age = isset($data->displayAge) ? $data->displayAge : ""; + $this->user->profile->photoURL = isset($data->image) ? $data->image->imageUrl : ""; + + $this->user->profile->address = isset($data->location) ? $data->location : ""; + $this->user->profile->language = isset($data->lang) ? $data->lang : ""; + + return $this->user->profile; + } + + /** + * {@inheritdoc} + */ + function getUserContacts() { + $userId = $this->getCurrentUserId(); + + $response = $this->api->get("user/{$userId}/contacts", array( + "format" => "json", + "count" => "max", + )); + + if ($this->api->http_code != 200) { + throw new Exception("User contacts request failed! {$this->providerId} returned an error: " . $this->errorMessageByStatus()); + } + + if (!isset($response->contacts) || !isset($response->contacts->contact) || (isset($response->errcode) && $response->errcode != 0)) { + return array(); + } + + $contacts = array(); + foreach ($response->contacts->contact as $item) { + $uc = new Hybrid_User_Contact(); + + $uc->identifier = isset($item->id) ? $item->id : ""; + $uc->email = $this->selectEmail($item->fields); + $uc->displayName = $this->selectName($item->fields); + $uc->photoURL = $this->selectPhoto($item->fields); + + $contacts[] = $uc; + } + + return $contacts; + } + + /** + * Returns current user id. + * + * @return string + * Current user ID. + * @throws Exception + */ + function getCurrentUserId() { + // Set headers to get refresh token. + $this->setAuthorizationHeaders("basic"); + + // Refresh tokens if needed. + $this->refreshToken(); + + // Set headers to make api call. + $this->setAuthorizationHeaders("bearer"); + + $response = $this->api->get("me/guid", array( + "format" => "json", + )); + + if (!isset($response->guid->value)) { + throw new Exception("User id request failed! {$this->providerId} returned an invalid response: " . Hybrid_Logger::dumpData($response)); + } + + return $response->guid->value; + } + + /** + * Utility function for returning values from XML-like objects. + * + * @param stdClass $vs + * Object. + * @param string $t + * Property name. + * @return mixed + */ + private function select($vs, $t) { + foreach ($vs as $v) { + if ($v->type == $t) { + return $v; + } + } + + return null; + } + + /** + * Parses user name. + * + * @param stdClass $v + * Object. + * @return string + * User name. + */ + private function selectName($v) { + $s = $this->select($v, "name"); + if (!$s) { + $s = $this->select($v, "nickname"); + return isset($s->value) ? $s->value : ""; + } + return isset($s->value) ? "{$s->value->givenName} {$s->value->familyName}" : ""; + } + + /** + * Parses photo URL. + * + * @param stdClass $v + * Object. + * @return string + * Photo URL. + */ + private function selectPhoto($v) { + $s = $this->select($v, "image"); + + return isset($s->value) ? $s->value->imageUrl : ""; + } + + /** + * Parses email. + * + * @param stdClass $v + * Object + * @return string + * An email address. + */ + private function selectEmail($v) { + $s = $this->select($v, "email"); + if (empty($s)) { + $s = $this->select($v, "yahooid"); + if (isset($s->value) && strpos($s->value, "@") === FALSE) { + $s->value .= "@yahoo.com"; + } + } + + return isset($s->value) ? $s->value : ""; + } + + /** + * Set correct Authorization headers. + * + * @param string $token_type + * Specify token type. + * + * @return void + */ + private function setAuthorizationHeaders($token_type) { + switch ($token_type) { + case "basic": + // The /get_token requires authorization header. + $token = base64_encode("{$this->config["keys"]["id"]}:{$this->config["keys"]["secret"]}"); + $this->api->curl_header = array( + "Authorization: Basic {$token}", + "Content-Type: application/x-www-form-urlencoded", + ); + break; + + case "bearer": + // Yahoo API requires the token to be passed as a Bearer within the authorization header. + $this->api->curl_header = array( + "Authorization: Bearer {$this->api->access_token}", + ); + break; + } + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/Storage.php b/e107_handlers/hybridauth/Hybrid/Storage.php index d82b4af9b..16a2f6cb2 100644 --- a/e107_handlers/hybridauth/Hybrid/Storage.php +++ b/e107_handlers/hybridauth/Hybrid/Storage.php @@ -1,141 +1,141 @@ -config("php_session_id", session_id()); - $this->config("version", Hybrid_Auth::$version); - } - - /** - * Saves a value in the config storage, or returns config if value is null - * - * @param string $key Config name - * @param string $value Config value - * @return array|null - */ - public function config($key, $value = null) { - $key = strtolower($key); - - if ($value) { - $_SESSION["HA::CONFIG"][$key] = serialize($value); - } elseif (isset($_SESSION["HA::CONFIG"][$key])) { - return unserialize($_SESSION["HA::CONFIG"][$key]); - } - - return null; - } - - /** - * Returns value from session storage - * - * @param string $key Key - * @return string|null - */ - public function get($key) { - $key = strtolower($key); - - if (isset($_SESSION["HA::STORE"], $_SESSION["HA::STORE"][$key])) { - return unserialize($_SESSION["HA::STORE"][$key]); - } - - return null; - } - - /** - * Saves a key value pair to the session storage - * - * @param string $key Key - * @param string $value Value - * @return void - */ - public function set($key, $value) { - $key = strtolower($key); - $_SESSION["HA::STORE"][$key] = serialize($value); - } - - /** - * Clear session storage - * @return void - */ - function clear() { - $_SESSION["HA::STORE"] = array(); - } - - /** - * Delete a specific key from session storage - * - * @param string $key Key - * @return void - */ - function delete($key) { - $key = strtolower($key); - - if (isset($_SESSION["HA::STORE"], $_SESSION["HA::STORE"][$key])) { - $f = $_SESSION['HA::STORE']; - unset($f[$key]); - $_SESSION["HA::STORE"] = $f; - } - } - - /** - * Delete all keys recursively from session storage - * - * @param string $key Key - * @retun void - */ - function deleteMatch($key) { - $key = strtolower($key); - - if (isset($_SESSION["HA::STORE"]) && count($_SESSION["HA::STORE"])) { - $f = $_SESSION['HA::STORE']; - foreach ($f as $k => $v) { - if (strstr($k, $key)) { - unset($f[$k]); - } - } - $_SESSION["HA::STORE"] = $f; - } - } - - /** - * Returns session storage as a serialized string - * @return string|null - */ - function getSessionData() { - if (isset($_SESSION["HA::STORE"])) { - return serialize($_SESSION["HA::STORE"]); - } - return null; - } - - /** - * Restores the session from serialized session data - * - * @param string $sessiondata Serialized session data - * @return void - */ - function restoreSessionData($sessiondata = null) { - $_SESSION["HA::STORE"] = unserialize($sessiondata); - } - -} +config("php_session_id", session_id()); + $this->config("version", Hybrid_Auth::$version); + } + + /** + * Saves a value in the config storage, or returns config if value is null + * + * @param string $key Config name + * @param string $value Config value + * @return array|null + */ + public function config($key, $value = null) { + $key = strtolower($key); + + if ($value) { + $_SESSION["HA::CONFIG"][$key] = serialize($value); + } elseif (isset($_SESSION["HA::CONFIG"][$key])) { + return unserialize($_SESSION["HA::CONFIG"][$key]); + } + + return null; + } + + /** + * Returns value from session storage + * + * @param string $key Key + * @return string|null + */ + public function get($key) { + $key = strtolower($key); + + if (isset($_SESSION["HA::STORE"], $_SESSION["HA::STORE"][$key])) { + return unserialize($_SESSION["HA::STORE"][$key]); + } + + return null; + } + + /** + * Saves a key value pair to the session storage + * + * @param string $key Key + * @param string $value Value + * @return void + */ + public function set($key, $value) { + $key = strtolower($key); + $_SESSION["HA::STORE"][$key] = serialize($value); + } + + /** + * Clear session storage + * @return void + */ + function clear() { + $_SESSION["HA::STORE"] = array(); + } + + /** + * Delete a specific key from session storage + * + * @param string $key Key + * @return void + */ + function delete($key) { + $key = strtolower($key); + + if (isset($_SESSION["HA::STORE"], $_SESSION["HA::STORE"][$key])) { + $f = $_SESSION['HA::STORE']; + unset($f[$key]); + $_SESSION["HA::STORE"] = $f; + } + } + + /** + * Delete all keys recursively from session storage + * + * @param string $key Key + * @retun void + */ + function deleteMatch($key) { + $key = strtolower($key); + + if (isset($_SESSION["HA::STORE"]) && count($_SESSION["HA::STORE"])) { + $f = $_SESSION['HA::STORE']; + foreach ($f as $k => $v) { + if (strstr($k, $key)) { + unset($f[$k]); + } + } + $_SESSION["HA::STORE"] = $f; + } + } + + /** + * Returns session storage as a serialized string + * @return string|null + */ + function getSessionData() { + if (isset($_SESSION["HA::STORE"])) { + return serialize($_SESSION["HA::STORE"]); + } + return null; + } + + /** + * Restores the session from serialized session data + * + * @param string $sessiondata Serialized session data + * @return void + */ + function restoreSessionData($sessiondata = null) { + $_SESSION["HA::STORE"] = unserialize($sessiondata); + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/User.php b/e107_handlers/hybridauth/Hybrid/User.php index 6461671a8..ccd49b970 100644 --- a/e107_handlers/hybridauth/Hybrid/User.php +++ b/e107_handlers/hybridauth/Hybrid/User.php @@ -1,40 +1,40 @@ -timestamp = time(); - $this->profile = new Hybrid_User_Profile(); - } - -} +timestamp = time(); + $this->profile = new Hybrid_User_Profile(); + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/User_Activity.php b/e107_handlers/hybridauth/Hybrid/User_Activity.php index 4a57e1623..5d0712ab6 100644 --- a/e107_handlers/hybridauth/Hybrid/User_Activity.php +++ b/e107_handlers/hybridauth/Hybrid/User_Activity.php @@ -1,55 +1,55 @@ -user = new stdClass(); - - // typically, we should have a few information about the user who created the event from social apis - $this->user->identifier = null; - $this->user->displayName = null; - $this->user->profileURL = null; - $this->user->photoURL = null; - } - -} +user = new stdClass(); + + // typically, we should have a few information about the user who created the event from social apis + $this->user->identifier = null; + $this->user->displayName = null; + $this->user->profileURL = null; + $this->user->photoURL = null; + } + +} diff --git a/e107_handlers/hybridauth/Hybrid/User_Contact.php b/e107_handlers/hybridauth/Hybrid/User_Contact.php index facbfc464..976595835 100644 --- a/e107_handlers/hybridauth/Hybrid/User_Contact.php +++ b/e107_handlers/hybridauth/Hybrid/User_Contact.php @@ -1,60 +1,60 @@ - - - 403 Forbidden - - - -

Directory access is forbidden.

- - + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + \ No newline at end of file diff --git a/e107_handlers/hybridauth/Hybrid/resources/config.php.tpl b/e107_handlers/hybridauth/Hybrid/resources/config.php.tpl index 92e8c9c8c..a718c1fce 100644 --- a/e107_handlers/hybridauth/Hybrid/resources/config.php.tpl +++ b/e107_handlers/hybridauth/Hybrid/resources/config.php.tpl @@ -1,72 +1,72 @@ - "#GLOBAL_HYBRID_AUTH_URL_BASE#", - - "providers" => array ( - // openid providers - "OpenID" => array ( - "enabled" => #OPENID_ADAPTER_STATUS# - ), - - "AOL" => array ( - "enabled" => #AOL_ADAPTER_STATUS# - ), - - "Yahoo" => array ( - "enabled" => #YAHOO_ADAPTER_STATUS#, - "keys" => array ( "id" => "#YAHOO_APPLICATION_APP_ID#", "secret" => "#YAHOO_APPLICATION_SECRET#" ) - ), - - "Google" => array ( - "enabled" => #GOOGLE_ADAPTER_STATUS#, - "keys" => array ( "id" => "#GOOGLE_APPLICATION_APP_ID#", "secret" => "#GOOGLE_APPLICATION_SECRET#" ) - ), - - "Facebook" => array ( - "enabled" => #FACEBOOK_ADAPTER_STATUS#, - "keys" => array ( "id" => "#FACEBOOK_APPLICATION_APP_ID#", "secret" => "#FACEBOOK_APPLICATION_SECRET#" ) - ), - - "Twitter" => array ( - "enabled" => #TWITTER_ADAPTER_STATUS#, - "keys" => array ( "key" => "#TWITTER_APPLICATION_KEY#", "secret" => "#TWITTER_APPLICATION_SECRET#" ) - ), - - // windows live - "Live" => array ( - "enabled" => #LIVE_ADAPTER_STATUS#, - "keys" => array ( "id" => "#LIVE_APPLICATION_APP_ID#", "secret" => "#LIVE_APPLICATION_SECRET#" ) - ), - - "MySpace" => array ( - "enabled" => #MYSPACE_ADAPTER_STATUS#, - "keys" => array ( "key" => "#MYSPACE_APPLICATION_KEY#", "secret" => "#MYSPACE_APPLICATION_SECRET#" ) - ), - - "LinkedIn" => array ( - "enabled" => #LINKEDIN_ADAPTER_STATUS#, - "keys" => array ( "key" => "#LINKEDIN_APPLICATION_KEY#", "secret" => "#LINKEDIN_APPLICATION_SECRET#" ) - ), - - "Foursquare" => array ( - "enabled" => #FOURSQUARE_ADAPTER_STATUS#, - "keys" => array ( "id" => "#FOURSQUARE_APPLICATION_APP_ID#", "secret" => "#FOURSQUARE_APPLICATION_SECRET#" ) - ), - ), - - // if you want to enable logging, set 'debug_mode' to true then provide a writable file by the web server on "debug_file" - "debug_mode" => false, - - "debug_file" => "" - ); + "#GLOBAL_HYBRID_AUTH_URL_BASE#", + + "providers" => array ( + // openid providers + "OpenID" => array ( + "enabled" => #OPENID_ADAPTER_STATUS# + ), + + "AOL" => array ( + "enabled" => #AOL_ADAPTER_STATUS# + ), + + "Yahoo" => array ( + "enabled" => #YAHOO_ADAPTER_STATUS#, + "keys" => array ( "id" => "#YAHOO_APPLICATION_APP_ID#", "secret" => "#YAHOO_APPLICATION_SECRET#" ) + ), + + "Google" => array ( + "enabled" => #GOOGLE_ADAPTER_STATUS#, + "keys" => array ( "id" => "#GOOGLE_APPLICATION_APP_ID#", "secret" => "#GOOGLE_APPLICATION_SECRET#" ) + ), + + "Facebook" => array ( + "enabled" => #FACEBOOK_ADAPTER_STATUS#, + "keys" => array ( "id" => "#FACEBOOK_APPLICATION_APP_ID#", "secret" => "#FACEBOOK_APPLICATION_SECRET#" ) + ), + + "Twitter" => array ( + "enabled" => #TWITTER_ADAPTER_STATUS#, + "keys" => array ( "key" => "#TWITTER_APPLICATION_KEY#", "secret" => "#TWITTER_APPLICATION_SECRET#" ) + ), + + // windows live + "Live" => array ( + "enabled" => #LIVE_ADAPTER_STATUS#, + "keys" => array ( "id" => "#LIVE_APPLICATION_APP_ID#", "secret" => "#LIVE_APPLICATION_SECRET#" ) + ), + + "MySpace" => array ( + "enabled" => #MYSPACE_ADAPTER_STATUS#, + "keys" => array ( "key" => "#MYSPACE_APPLICATION_KEY#", "secret" => "#MYSPACE_APPLICATION_SECRET#" ) + ), + + "LinkedIn" => array ( + "enabled" => #LINKEDIN_ADAPTER_STATUS#, + "keys" => array ( "key" => "#LINKEDIN_APPLICATION_KEY#", "secret" => "#LINKEDIN_APPLICATION_SECRET#" ) + ), + + "Foursquare" => array ( + "enabled" => #FOURSQUARE_ADAPTER_STATUS#, + "keys" => array ( "id" => "#FOURSQUARE_APPLICATION_APP_ID#", "secret" => "#FOURSQUARE_APPLICATION_SECRET#" ) + ), + ), + + // if you want to enable logging, set 'debug_mode' to true then provide a writable file by the web server on "debug_file" + "debug_mode" => false, + + "debug_file" => "" + ); diff --git a/e107_handlers/hybridauth/Hybrid/resources/index.html b/e107_handlers/hybridauth/Hybrid/resources/index.html index 065d2da5e..c942a79ce 100644 --- a/e107_handlers/hybridauth/Hybrid/resources/index.html +++ b/e107_handlers/hybridauth/Hybrid/resources/index.html @@ -1,10 +1,10 @@ - - - 403 Forbidden - - - -

Directory access is forbidden.

- - + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + \ No newline at end of file diff --git a/e107_handlers/hybridauth/Hybrid/resources/openid_policy.html b/e107_handlers/hybridauth/Hybrid/resources/openid_policy.html index bf5c52c35..01462daec 100644 --- a/e107_handlers/hybridauth/Hybrid/resources/openid_policy.html +++ b/e107_handlers/hybridauth/Hybrid/resources/openid_policy.html @@ -1,10 +1,10 @@ - - - OpenID Policy - - - - + + + OpenID Policy + + + + \ No newline at end of file diff --git a/e107_handlers/hybridauth/Hybrid/resources/openid_realm.html b/e107_handlers/hybridauth/Hybrid/resources/openid_realm.html index e26a5a17d..78b1b1d62 100644 --- a/e107_handlers/hybridauth/Hybrid/resources/openid_realm.html +++ b/e107_handlers/hybridauth/Hybrid/resources/openid_realm.html @@ -1,13 +1,13 @@ - - - HybridAuth Endpoint - - - - -

HybridAuth

- Open Source Social Sign On PHP Library. -
- hybridauth.sourceforge.net/ - - + + + HybridAuth Endpoint + + + + +

HybridAuth

+ Open Source Social Sign On PHP Library. +
+ hybridauth.sourceforge.net/ + + diff --git a/e107_handlers/hybridauth/Hybrid/resources/openid_xrds.xml b/e107_handlers/hybridauth/Hybrid/resources/openid_xrds.xml index 9d50170fa..ab94e5c01 100644 --- a/e107_handlers/hybridauth/Hybrid/resources/openid_xrds.xml +++ b/e107_handlers/hybridauth/Hybrid/resources/openid_xrds.xml @@ -1,12 +1,12 @@ - - - - - http://specs.openid.net/auth/2.0/return_to - {RETURN_TO_URL} - - + + + + + http://specs.openid.net/auth/2.0/return_to + {RETURN_TO_URL} + + \ No newline at end of file diff --git a/e107_handlers/hybridauth/Hybrid/resources/windows_live_channel.html b/e107_handlers/hybridauth/Hybrid/resources/windows_live_channel.html index dadcf1911..5d864d7e8 100644 --- a/e107_handlers/hybridauth/Hybrid/resources/windows_live_channel.html +++ b/e107_handlers/hybridauth/Hybrid/resources/windows_live_channel.html @@ -1,37 +1,37 @@ - - - - "; - $mes = e107::getMessage(); - $mes->addDebug("Target: {$tagid}"); - - if($navMode === false) - { - $text .= "
"; - } - - return $text; - } - - - /** - * @param string $oldpath - path to pre-moved file (no e107 constants) - * @param string $newpath - new path to move file to (no e107 constants) - * @return bool|string returns false if duplciate entry found otherwise return new path. - */ - function checkDupe($oldpath, $newpath) - { - $mes = e107::getMessage(); - $tp = e107::getParser(); - $sql = e107::getDb(); - - // $mes->addDebug("checkDupe(): newpath=".$newpath."
oldpath=".$oldpath."
".print_r($upload,TRUE)); - if(file_exists($newpath) && ($f = e107::getFile()->get_file_info($oldpath,TRUE))) - { - $this->log($newpath." already exists and will be renamed during import."); - $mes->addWarning($newpath." already exists and was renamed during import."); - $file = $f['pathinfo']['filename']."_.".$f['pathinfo']['extension']; - $newpath = $this->getPath($f['mime']).'/'.$file; - } - - if($sql->select("core_media","media_url","media_url LIKE '%".$tp->createConstants($newpath,'rel')."' LIMIT 1")) - { - // $mes->addWarning($newpath." detected in media-manager."); - $this->log("Import not performed. ".$newpath." detected in media table already."); - - return false; - //$row = $sql->fetch(); - //$newpath = $row['media_url']; // causes trouble with importFile() if {e_MEDIA_CONSTANT} returned. - } - - return $newpath; - } - - - /** - * @param string|array $type array('prefix'=>'', 'pattern'=>'', 'path'=>'', 'name'=>'') - * @param string $addPrefix - * @return array - */ - function getGlyphs($type='fa4', $addPrefix = '') - { - $icons = array(); - - if($type === 'bs2' || $type === 'bs3' || $type === 'fab' || $type === 'fas') - { - - $matches = array(); - - $matches['bs2'] = array( - 'glass','music','search','envelope','heart','star','star-empty','user','film','th-large','th','th-list','ok', - 'remove','zoom-in','zoom-out','off','signal','cog','trash','home','file','time','road','download-alt','download', - 'upload','inbox','play-circle','repeat','refresh','list-alt','lock','flag','headphones','volume-off','volume-down', - 'volume-up','qrcode','barcode','tag','tags','book','bookmark','print','camera','font','bold','italic','text-height', - 'text-width','align-left','align-center','align-right','align-justify','list','indent-left','indent-right', - 'facetime-video','picture','pencil','map-marker','adjust','tint','edit','share','check','move','step-backward', - 'fast-backward','backward','play','pause','stop','forward','fast-forward','step-forward','eject','chevron-left', - 'chevron-right','plus-sign','minus-sign','remove-sign','ok-sign','question-sign','info-sign','screenshot', - 'remove-circle','ok-circle','ban-circle','arrow-left','arrow-right','arrow-up','arrow-down','share-alt', - 'resize-full','resize-small','plus','minus','asterisk','exclamation-sign','gift','leaf','fire','eye-open', - 'eye-close','warning-sign','plane','calendar','random','comment','magnet','chevron-up','chevron-down', - 'retweet','shopping-cart','folder-close','folder-open','resize-vertical','resize-horizontal','hdd', - 'bullhorn','bell','certificate','thumbs-up','thumbs-down','hand-right','hand-left','hand-up','hand-down', - 'circle-arrow-right','circle-arrow-left','circle-arrow-up','circle-arrow-down','globe','wrench','tasks', - 'filter','briefcase','fullscreen' - ); - - - $matches['bs3'] = array( - 'adjust','align-center','align-justify','align-left','align-right','arrow-down','arrow-left','arrow-right','arrow-up','asterisk','backward','ban-circle','barcode','bell','bold','book - ','bookmark','briefcase','bullhorn','calendar','camera','certificate','check','chevron-down','chevron-left','chevron-right','chevron-up','circle-arrow-down','circle-arrow-left','circle-arrow-right - ','circle-arrow-up','cloud','cloud-download','cloud-upload','cog','collapse-down','collapse-up','comment','compressed','copyright-mark','credit-card','cutlery','dashboard','download','download-alt - ','earphone','edit','eject','envelope','euro','exclamation-sign','expand','export','eye-close','eye-open','facetime-video','fast-backward','fast-forward','file','film','filter','fire','flag - ','flash','floppy-disk','floppy-open','floppy-remove','floppy-save','floppy-saved','folder-close','folder-open','font','forward','fullscreen','gbp','gift - ','glass','globe','hand-down','hand-left','hand-right','hand-up','hd-video','hdd','header','headphones','heart','heart-empty','home','import','inbox','indent-left','indent-right','info-sign','italic','leaf','link','list - ','list-alt','lock','log-in','log-out','magnet','map-marker','minus','minus-sign','move','music','new-window','off','ok','ok-circle','ok-sign','open','paperclip','pause','pencil','phone','phone-alt','picture - ','plane','play','play-circle','plus','plus-sign','print','pushpin','qrcode','question-sign','random','record','refresh','registration-mark','remove','remove-circle','remove-sign','repeat','resize-full','resize-horizontal - ','resize-small','resize-vertical','retweet','road','save','saved','screenshot','sd-video','search','send','share','share-alt','shopping-cart','signal','sort','sort-by-alphabet','sort-by-alphabet-alt - ','sort-by-attributes','sort-by-attributes-alt','sort-by-order','sort-by-order-alt','sound-5-1','sound-6-1','sound-7-1','sound-dolby','sound-stereo','star','stats','step-backward','step-forward','stop - ','subtitles','tag','tags','tasks','text-height','text-width','th','th-large','th-list','thumbs-down','thumbs-up','time','tint','tower','transfer','trash','tree-conifer','tree-deciduous','unchecked','upload - ','usd','user','volume-down','volume-off','volume-up','warning-sign','wrench','zoom-in','zoom-out' - ); - - - - $matches['fab'] = array( "500px", "accessible-icon", "accusoft", "acquisitions-incorporated", "adn", "adobe", "adversal", "affiliatetheme", "algolia", "alipay", "amazon", "amazon-pay", "amilia", "android", "angellist", - "angrycreative", "angular", "app-store", "app-store-ios", "apper", "apple", "apple-pay", "artstation", "asymmetrik", "atlassian", "audible", "autoprefixer", "avianex", "aviato", "aws", "bandcamp", "behance", "behance-square", - "bimobject", "bitbucket", "bitcoin", "bity", "black-tie", "blackberry", "blogger", "blogger-b", "bluetooth", "bluetooth-b", "btc", "buromobelexperte", "buysellads", "canadian-maple-leaf", "cc-amazon-pay", "cc-amex", - "cc-apple-pay", "cc-diners-club", "cc-discover", "cc-jcb", "cc-mastercard", "cc-paypal", "cc-stripe", "cc-visa", "centercode", "centos", "chrome", "cloudscale", "cloudsmith", "cloudversify", "codepen", "codiepie", - "confluence", "connectdevelop", "contao", "cpanel", "creative-commons", "creative-commons-by", "creative-commons-nc", "creative-commons-nc-eu", "creative-commons-nc-jp", "creative-commons-nd", "creative-commons-pd", - "creative-commons-pd-alt", "creative-commons-remix", "creative-commons-sa", "creative-commons-sampling", "creative-commons-sampling-plus", "creative-commons-share", "creative-commons-zero", "critical-role", "css3", - "css3-alt", "cuttlefish", "d-and-d", "d-and-d-beyond", "dashcube", "delicious", "deploydog", "deskpro", "dev", "deviantart", "dhl", "diaspora", "digg", "digital-ocean", "discord", "discourse", "dochub", "docker", - "draft2digital", "dribbble", "dribbble-square", "dropbox", "drupal", "dyalog", "earlybirds", "ebay", "edge", "elementor", "ello", "ember", "empire", "envira", "erlang", "ethereum", "etsy", "expeditedssl", "facebook", - "facebook-f", "facebook-messenger", "facebook-square", "fantasy-flight-games", "fedex", "fedora", "figma", "firefox", "first-order", "first-order-alt", "firstdraft", "flickr", "flipboard", "fly", "font-awesome", - "font-awesome-alt", "font-awesome-flag", "font-awesome-logo-full", "fonticons", "fonticons-fi", "fort-awesome", "fort-awesome-alt", "forumbee", "foursquare", "free-code-camp", "freebsd", "fulcrum", "galactic-republic", - "galactic-senate", "get-pocket", "gg", "gg-circle", "git", "git-square", "github", "github-alt", "github-square", "gitkraken", "gitlab", "gitter", "glide", "glide-g", "gofore", "goodreads", "goodreads-g", "google", - "google-drive", "google-play", "google-plus", "google-plus-g", "google-plus-square", "google-wallet", "gratipay", "grav", "gripfire", "grunt", "gulp", "hacker-news", "hacker-news-square", "hackerrank", "hips", - "hire-a-helper", "hooli", "hornbill", "hotjar", "houzz", "html5", "hubspot", "imdb", "instagram", "intercom", "internet-explorer", "invision", "ioxhost", "itunes", "itunes-note", "java", "jedi-order", "jenkins", - "jira", "joget", "joomla", "js", "js-square", "jsfiddle", "kaggle", "keybase", "keycdn", "kickstarter", "kickstarter-k", "korvue", "laravel", "lastfm", "lastfm-square", "leanpub", "less", "line", "linkedin", - "linkedin-in", "linode", "linux", "lyft", "magento", "mailchimp", "mandalorian", "markdown", "mastodon", "maxcdn", "medapps", "medium", "medium-m", "medrt", "meetup", "megaport", "mendeley", "microsoft", "mix", - "mixcloud", "mizuni", "modx", "monero", "napster", "neos", "nimblr", "nintendo-switch", "node", "node-js", "npm", "ns8", "nutritionix", "odnoklassniki", "odnoklassniki-square", "old-republic", "opencart", - "openid", "opera", "optin-monster", "osi", "page4", "pagelines", "palfed", "patreon", "paypal", "penny-arcade", "periscope", "phabricator", "phoenix-framework", "phoenix-squadron", "php", "pied-piper", - "pied-piper-alt", "pied-piper-hat", "pied-piper-pp", "pinterest", "pinterest-p", "pinterest-square", "playstation", "product-hunt", "pushed", "python", "qq", "quinscape", "quora", "r-project", "raspberry-pi", - "ravelry", "react", "reacteurope", "readme", "rebel", "red-river", "reddit", "reddit-alien", "reddit-square", "redhat", "renren", "replyd", "researchgate", "resolving", "rev", "rocketchat", "rockrms", "safari", - "sass", "schlix", "scribd", "searchengin", "sellcast", "sellsy", "servicestack", "shirtsinbulk", "shopware", "simplybuilt", "sistrix", "sith", "sketch", "skyatlas", "skype", "slack", "slack-hash", "slideshare", - "snapchat", "snapchat-ghost", "snapchat-square", "soundcloud", "sourcetree", "speakap", "spotify", "squarespace", "stack-exchange", "stack-overflow", "staylinked", "steam", "steam-square", "steam-symbol", - "sticker-mule", "strava", "stripe", "stripe-s", "studiovinari", "stumbleupon", "stumbleupon-circle", "superpowers", "supple", "suse", "teamspeak", "telegram", "telegram-plane", "tencent-weibo", "the-red-yeti", - "themeco", "themeisle", "think-peaks", "trade-federation", "trello", "tripadvisor", "tumblr", "tumblr-square", "twitch", "twitter", "twitter-square", "typo3", "uber", "ubuntu", "uikit", "uniregistry", - "untappd", "ups", "usb", "usps", "ussunnah", "vaadin", "viacoin", "viadeo", "viadeo-square", "viber", "vimeo", "vimeo-square", "vimeo-v", "vine", "vk", "vnv", "vuejs", "weebly", "weibo", "weixin", - "whatsapp", "whatsapp-square", "whmcs", "wikipedia-w", "windows", "wix", "wizards-of-the-coast", "wolf-pack-battalion", "wordpress", "wordpress-simple", "wpbeginner", "wpexplorer", "wpforms", "wpressr", - "xbox", "xing", "xing-square", "y-combinator", "yahoo", "yandex", "yandex-international", "yarn", "yelp", "yoast", "youtube", "youtube-square", "zhihu", - ); - - $matches['fas'] = array( - "ad", "address-book", "address-card", "adjust", "air-freshener", "align-center", "align-justify", "align-left", "align-right", "allergies", "ambulance", "american-sign-language-interpreting", "anchor", - "angle-double-down", "angle-double-left", "angle-double-right", "angle-double-up", "angle-down", "angle-left", "angle-right", "angle-up", "angry", "ankh", "apple-alt", "archive", "archway", "arrow-alt-circle-down", - "arrow-alt-circle-left", "arrow-alt-circle-right", "arrow-alt-circle-up", "arrow-circle-down", "arrow-circle-left", "arrow-circle-right", "arrow-circle-up", "arrow-down", "arrow-left", "arrow-right", "arrow-up", - "arrows-alt", "arrows-alt-h", "arrows-alt-v", "assistive-listening-systems", "asterisk", "at", "atlas", "atom", "audio-description", "award", "baby", "baby-carriage", "backspace", "backward", "bacon", "balance-scale", - "ban", "band-aid", "barcode", "bars", "baseball-ball", "basketball-ball", "bath", "battery-empty", "battery-full", "battery-half", "battery-quarter", "battery-three-quarters", "bed", "beer", "bell", "bell-slash", - "bezier-curve", "bible", "bicycle", "binoculars", "biohazard", "birthday-cake", "blender", "blender-phone", "blind", "blog", "bold", "bolt", "bomb", "bone", "bong", "book", "book-dead", "book-medical", "book-open", - "book-reader", "bookmark", "bowling-ball", "box", "box-open", "boxes", "braille", "brain", "bread-slice", "briefcase", "briefcase-medical", "broadcast-tower", "broom", "brush", "bug", "building", "bullhorn", "bullseye", - "burn", "bus", "bus-alt", "business-time", "calculator", "calendar", "calendar-alt", "calendar-check", "calendar-day", "calendar-minus", "calendar-plus", "calendar-times", "calendar-week", "camera", "camera-retro", - "campground", "candy-cane", "cannabis", "capsules", "car", "car-alt", "car-battery", "car-crash", "car-side", "caret-down", "caret-left", "caret-right", "caret-square-down", "caret-square-left", "caret-square-right", - "caret-square-up", "caret-up", "carrot", "cart-arrow-down", "cart-plus", "cash-register", "cat", "certificate", "chair", "chalkboard", "chalkboard-teacher", "charging-station", "chart-area", "chart-bar", "chart-line", - "chart-pie", "check", "check-circle", "check-double", "check-square", "cheese", "chess", "chess-bishop", "chess-board", "chess-king", "chess-knight", "chess-pawn", "chess-queen", "chess-rook", "chevron-circle-down", - "chevron-circle-left", "chevron-circle-right", "chevron-circle-up", "chevron-down", "chevron-left", "chevron-right", "chevron-up", "child", "church", "circle", "circle-notch", "city", "clinic-medical", "clipboard", - "clipboard-check", "clipboard-list", "clock", "clone", "closed-captioning", "cloud", "cloud-download-alt", "cloud-meatball", "cloud-moon", "cloud-moon-rain", "cloud-rain", "cloud-showers-heavy", "cloud-sun", - "cloud-sun-rain", "cloud-upload-alt", "cocktail", "code", "code-branch", "coffee", "cog", "cogs", "coins", "columns", "comment", "comment-alt", "comment-dollar", "comment-dots", "comment-medical", "comment-slash", - "comments", "comments-dollar", "compact-disc", "compass", "compress", "compress-arrows-alt", "concierge-bell", "cookie", "cookie-bite", "copy", "copyright", "couch", "credit-card", "crop", "crop-alt", "cross", - "crosshairs", "crow", "crown", "crutch", "cube", "cubes", "cut", "database", "deaf", "democrat", "desktop", "dharmachakra", "diagnoses", "dice", "dice-d20", "dice-d6", "dice-five", "dice-four", "dice-one", "dice-six", - "dice-three", "dice-two", "digital-tachograph", "directions", "divide", "dizzy", "dna", "dog", "dollar-sign", "dolly", "dolly-flatbed", "donate", "door-closed", "door-open", "dot-circle", "dove", "download", - "drafting-compass", "dragon", "draw-polygon", "drum", "drum-steelpan", "drumstick-bite", "dumbbell", "dumpster", "dumpster-fire", "dungeon", "edit", "egg", "eject", "ellipsis-h", "ellipsis-v", "envelope", - "envelope-open", "envelope-open-text", "envelope-square", "equals", "eraser", "ethernet", "euro-sign", "exchange-alt", "exclamation", "exclamation-circle", "exclamation-triangle", "expand", "expand-arrows-alt", - "external-link-alt", "external-link-square-alt", "eye", "eye-dropper", "eye-slash", "fast-backward", "fast-forward", "fax", "feather", "feather-alt", "female", "fighter-jet", "file", "file-alt", "file-archive", - "file-audio", "file-code", "file-contract", "file-csv", "file-download", "file-excel", "file-export", "file-image", "file-import", "file-invoice", "file-invoice-dollar", "file-medical", "file-medical-alt", "file-pdf", - "file-powerpoint", "file-prescription", "file-signature", "file-upload", "file-video", "file-word", "fill", "fill-drip", "film", "filter", "fingerprint", "fire", "fire-alt", "fire-extinguisher", "first-aid", "fish", "fist-raised", "flag", "flag-checkered", "flag-usa", "flask", "flushed", "folder", "folder-minus", "folder-open", "folder-plus", "font", "font-awesome-logo-full", "football-ball", "forward", "frog", "frown", "frown-open", "funnel-dollar", "futbol", "gamepad", "gas-pump", "gavel", "gem", "genderless", "ghost", "gift", "gifts", "glass-cheers", "glass-martini", "glass-martini-alt", "glass-whiskey", "glasses", "globe", "globe-africa", "globe-americas", "globe-asia", "globe-europe", "golf-ball", "gopuram", "graduation-cap", "greater-than", "greater-than-equal", "grimace", "grin", "grin-alt", "grin-beam", "grin-beam-sweat", "grin-hearts", "grin-squint", "grin-squint-tears", "grin-stars", "grin-tears", "grin-tongue", "grin-tongue-squint", "grin-tongue-wink", "grin-wink", "grip-horizontal", "grip-lines", "grip-lines-vertical", "grip-vertical", "guitar", "h-square", "hamburger", "hammer", "hamsa", "hand-holding", "hand-holding-heart", "hand-holding-usd", "hand-lizard", "hand-middle-finger", "hand-paper", "hand-peace", "hand-point-down", "hand-point-left", "hand-point-right", "hand-point-up", "hand-pointer", "hand-rock", "hand-scissors", "hand-spock", "hands", "hands-helping", "handshake", "hanukiah", "hard-hat", "hashtag", "hat-wizard", "haykal", "hdd", "heading", "headphones", "headphones-alt", "headset", "heart", "heart-broken", "heartbeat", "helicopter", "highlighter", "hiking", "hippo", "history", "hockey-puck", "holly-berry", "home", "horse", "horse-head", "hospital", "hospital-alt", "hospital-symbol", "hot-tub", "hotdog", "hotel", "hourglass", "hourglass-end", "hourglass-half", "hourglass-start", "house-damage", "hryvnia", "i-cursor", "ice-cream", "icicles", "id-badge", "id-card", "id-card-alt", "igloo", "image", "images", "inbox", "indent", "industry", "infinity", "info", "info-circle", "italic", "jedi", "joint", "journal-whills", "kaaba", "key", "keyboard", "khanda", "kiss", "kiss-beam", "kiss-wink-heart", "kiwi-bird", "landmark", "language", "laptop", "laptop-code", "laptop-medical", "laugh", "laugh-beam", "laugh-squint", "laugh-wink", "layer-group", "leaf", "lemon", "less-than", "less-than-equal", "level-down-alt", "level-up-alt", "life-ring", "lightbulb", "link", "lira-sign", "list", "list-alt", "list-ol", "list-ul", "location-arrow", "lock", "lock-open", "long-arrow-alt-down", "long-arrow-alt-left", "long-arrow-alt-right", "long-arrow-alt-up", "low-vision", "luggage-cart", "magic", "magnet", "mail-bulk", "male", "map", "map-marked", "map-marked-alt", "map-marker", "map-marker-alt", "map-pin", "map-signs", "marker", "mars", "mars-double", "mars-stroke", "mars-stroke-h", "mars-stroke-v", "mask", "medal", "medkit", "meh", "meh-blank", "meh-rolling-eyes", "memory", "menorah", "mercury", "meteor", "microchip", "microphone", "microphone-alt", "microphone-alt-slash", "microphone-slash", "microscope", "minus", "minus-circle", "minus-square", "mitten", "mobile", "mobile-alt", "money-bill", "money-bill-alt", "money-bill-wave", "money-bill-wave-alt", "money-check", "money-check-alt", "monument", "moon", "mortar-pestle", "mosque", "motorcycle", "mountain", "mouse-pointer", "mug-hot", "music", "network-wired", "neuter", "newspaper", "not-equal", "notes-medical", "object-group", "object-ungroup", "oil-can", "om", "otter", "outdent", "pager", "paint-brush", "paint-roller", "palette", "pallet", "paper-plane", "paperclip", "parachute-box", "paragraph", "parking", "passport", "pastafarianism", "paste", "pause", "pause-circle", "paw", "peace", "pen", "pen-alt", "pen-fancy", "pen-nib", "pen-square", "pencil-alt", "pencil-ruler", "people-carry", "pepper-hot", "percent", "percentage", "person-booth", "phone", "phone-slash", "phone-square", "phone-volume", "piggy-bank", "pills", "pizza-slice", "place-of-worship", "plane", "plane-arrival", "plane-departure", "play", "play-circle", "plug", "plus", "plus-circle", "plus-square", "podcast", "poll", "poll-h", "poo", "poo-storm", "poop", "portrait", "pound-sign", "power-off", "pray", "praying-hands", "prescription", "prescription-bottle", "prescription-bottle-alt", "print", "procedures", "project-diagram", "puzzle-piece", "qrcode", "question", "question-circle", "quidditch", "quote-left", "quote-right", "quran", "radiation", "radiation-alt", "rainbow", "random", "receipt", "recycle", "redo", "redo-alt", "registered", "reply", "reply-all", "republican", "restroom", "retweet", "ribbon", "ring", "road", "robot", "rocket", "route", "rss", "rss-square", "ruble-sign", "ruler", "ruler-combined", "ruler-horizontal", "ruler-vertical", "running", "rupee-sign", "sad-cry", "sad-tear", "satellite", "satellite-dish", "save", "school", "screwdriver", "scroll", "sd-card", "search", "search-dollar", "search-location", "search-minus", "search-plus", "seedling", "server", "shapes", "share", "share-alt", "share-alt-square", "share-square", "shekel-sign", "shield-alt", "ship", "shipping-fast", "shoe-prints", "shopping-bag", "shopping-basket", "shopping-cart", "shower", "shuttle-van", "sign", "sign-in-alt", "sign-language", "sign-out-alt", "signal", "signature", "sim-card", "sitemap", "skating", "skiing", "skiing-nordic", "skull", "skull-crossbones", "slash", "sleigh", "sliders-h", "smile", "smile-beam", "smile-wink", "smog", "smoking", "smoking-ban", "sms", "snowboarding", "snowflake", "snowman", "snowplow", "socks", "solar-panel", "sort", "sort-alpha-down", "sort-alpha-up", "sort-amount-down", "sort-amount-up", "sort-down", "sort-numeric-down", "sort-numeric-up", "sort-up", "spa", "space-shuttle", "spider", "spinner", "splotch", "spray-can", "square", "square-full", "square-root-alt", "stamp", "star", "star-and-crescent", "star-half", "star-half-alt", "star-of-david", "star-of-life", "step-backward", "step-forward", "stethoscope", "sticky-note", "stop", "stop-circle", "stopwatch", "store", "store-alt", "stream", "street-view", "strikethrough", "stroopwafel", "subscript", "subway", "suitcase", "suitcase-rolling", "sun", "superscript", "surprise", "swatchbook", "swimmer", "swimming-pool", "synagogue", "sync", "sync-alt", "syringe", "table", "table-tennis", "tablet", "tablet-alt", "tablets", "tachometer-alt", "tag", "tags", "tape", "tasks", "taxi", "teeth", "teeth-open", "temperature-high", "temperature-low", "tenge", "terminal", "text-height", "text-width", "th", "th-large", "th-list", "theater-masks", "thermometer", "thermometer-empty", "thermometer-full", "thermometer-half", "thermometer-quarter", "thermometer-three-quarters", "thumbs-down", "thumbs-up", "thumbtack", "ticket-alt", "times", "times-circle", "tint", "tint-slash", "tired", "toggle-off", "toggle-on", "toilet", "toilet-paper", "toolbox", "tools", "tooth", "torah", "torii-gate", "tractor", "trademark", "traffic-light", "train", "tram", "transgender", "transgender-alt", "trash", "trash-alt", "trash-restore", "trash-restore-alt", "tree", "trophy", "truck", "truck-loading", "truck-monster", "truck-moving", "truck-pickup", "tshirt", "tty", "tv", "umbrella", "umbrella-beach", "underline", "undo", "undo-alt", "universal-access", "university", "unlink", "unlock", "unlock-alt", "upload", "user", "user-alt", "user-alt-slash", "user-astronaut", "user-check", "user-circle", "user-clock", "user-cog", "user-edit", "user-friends", "user-graduate", "user-injured", "user-lock", "user-md", "user-minus", "user-ninja", "user-nurse", "user-plus", "user-secret", "user-shield", "user-slash", "user-tag", "user-tie", "user-times", "users", "users-cog", "utensil-spoon", "utensils", "vector-square", "venus", "venus-double", "venus-mars", "vial", "vials", "video", "video-slash", "vihara", "volleyball-ball", "volume-down", "volume-mute", "volume-off", "volume-up", "vote-yea", "vr-cardboard", "walking", "wallet", "warehouse", "water", "weight", "weight-hanging", "wheelchair", "wifi", "wind", "window-close", "window-maximize", "window-minimize", "window-restore", "wine-bottle", "wine-glass", "wine-glass-alt", "won-sign", "wrench", "x-ray", "yen-sign", "yin-yang", - - ); - - foreach($matches[$type] as $match) - { - $icons[] = $addPrefix.$match; - } - - return $icons; - } - - - - if(is_array($type)) - { - $prefix = $type['prefix']; - $pattern = $type['pattern']; - $path = $type['path']; - $type = $type['name']; - - } - - - - $cache = e107::getCache(); - - $cachTag = !empty($addPrefix) ? "Glyphs_".$addPrefix."_".$type : "Glyphs_".$type; - - - if($data = $cache->retrieve($cachTag ,360,true,true)) - { - return e107::unserialize($data); - } - - - if($type === 'fa4') - { - $pattern = '/\.(fa-(?:\w+(?:-)?)+):before/'; - $path = e107::getLibrary()->getPath('fontawesome'); - $subject = file_get_contents($path.'css/font-awesome.css'); - $prefix = 'fa-'; - } - elseif($type === 'fa3') - { - $pattern = '/\.(icon-(?:\w+(?:-)?)+):before/'; - $subject = file_get_contents(e_WEB_JS.'font-awesome/css/font-awesome.css'); - $prefix = 'fa-'; - } - elseif(!empty($pattern) && !empty($path)) - { - $pattern = '/'.$pattern.'/'; - if(substr($path,0,4) === 'http') - { - $subject = e107::getFile()->getRemoteContent($path); - } - else - { - $path = e107::getParser()->replaceConstants($path); - $subject = file_get_contents($path); - } - - - - } - - - $prefixLength = !empty($prefix) ? strlen($prefix) : 3; - - if(!empty($pattern) && !empty($subject)) - { - preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER); - - foreach($matches as $match) - { - $icons[] = $addPrefix.substr($match[1],$prefixLength); - } - } - - if(empty($icons)) // failed to produce a result so don't cache it. . - { - return array(); - } - - $data = e107::serialize($icons,'json'); - - $cache->set_sys($cachTag ,$data,true,true); - - return $icons; - - } - - - - - public function getPath($mime, $path=null) - { - $mes = e107::getMessage(); - - list($pmime,$tmp) = explode('/',$mime); - unset($tmp); - - if(!vartrue($this->mimePaths[$pmime])) - { - $this->log("Couldn't detect mime-type ($mime)."); - $text = $text = str_replace('[x]',$mime,IMALAN_111); //FIXME LAN IMALAN_112 is not generic. This method can be called from anywhere, not only e107_admin/image.php. - $mes->add($text, E_MESSAGE_ERROR); - return FALSE; - } - - if(!empty($path)) - { - $dir = e_MEDIA."plugins/".e107::getParser()->filter($path,'w'); - } - else - { - $dir = $this->mimePaths[$pmime].date("Y-m"); - } - - - if(!is_dir($dir)) - { - if(!mkdir($dir, 0755,true)) - { - - $this->log("Couldn't create folder ($dir)."); - $text = str_replace('[x]',$dir,IMALAN_112); - $mes->add($text, E_MESSAGE_ERROR); - return FALSE; - }; - } - return $dir; - } - - /** - * detected Media Type from Media URL - * @param string $mediaURL - * @return int|string - */ - public function detectType($mediaURL) - { - $type = pathinfo($mediaURL,PATHINFO_EXTENSION); - - foreach($this->mimeExtensions as $key=>$exts) - { - if(!in_array($type, $exts)) - { - continue; - } - - return $key; - } - - return null; - } - - - /** - * @param string $default eg. {e_MEDIA_VIDEO}2018-10/myvideo.mp4 - * @param array $options - * @return bool|string - */ - public function previewTag($default, $options=array()) - { - $tp = e107::getParser(); - - $type = !empty($options['type']) ? $options['type'] : $this->detectType($default); - - $width = vartrue($options['w'], 220); - $height = vartrue($options['h'], 190); - $preview = ''; - - switch($type) - { - - case "video": - $preview = $tp->toVideo($default, array('w'=>$width, 'h'=> ($height - 50))); - // $previewURL = $tp->toVideo($default, array('mode'=>'url')); - break; - - case "audio": - $preview = $tp->toAudio($default); - // $previewURL = false; - break; - - case "image": - $preview = $tp->toImage($default, array('w'=>$width, 'h'=>$height, 'class'=>'image-selector img-responsive img-fluid', 'legacy'=>varset($options['legacyPath']))); - // $previewURL = $tp->thumbUrl($default, array('w'=>800)); - break; - - case "application": // file. - // $preview = $tp->toImage($default, array('w'=>$width, 'h'=>$height, 'class'=>'image-selector img-responsive img-fluid')); - // $previewURL = $tp->thumbUrl($default, array('w'=>800)); - break; - - case "glyph": - $preview = $tp->toGlyph($default); - break; - - case "icon": - $preview = $tp->toIcon($default); - // $previewURL = false; - break; - - default: // blank - $preview = null; - - } - - return $preview; - } - - - - - public function mediaData($sc_path) - { - if(!$sc_path) return array(); - - $mes = e107::getMessage(); - $path = e107::getParser()->replaceConstants($sc_path); - - if(!is_readable($path)) - { - $mes->addError("Couldn't read file: {$path}"); - $this->log("Couldn't read file: {$path}"); - return FALSE; - } - - $info = e107::getFile()->get_file_info($path,true); - - - - $this->log("File info for $path : ".print_r($info,true)); - - return array( - 'media_type' => vartrue($info['mime']), - 'media_datestamp' => time(), - 'media_url' => e107::getParser()->createConstants($info['fullpath'], 'rel'), - 'media_size' => filesize($info['fullpath']), - 'media_author' => USERID, - 'media_usedby' => '', - 'media_tags' => '', - 'media_dimensions' => $info['img-width']." x ".$info['img-height'] - ); - } - - - - - - - - - - - - public function log($message) - { - if($this->logging == false) return; - $insert = "\n\n".date('r')."\n".$message; - file_put_contents(e_LOG."mediaUpload.log",$insert,FILE_APPEND | LOCK_EX); - } - - - /** - * Import a file into the Media Manager - * @param string $file Path to file - * @param string $category media-category to import into - * @param null|array $opts('path'=> Custom Folder (optional)) - * @param array $new_data - Additional media info to save. - * @return bool|string - */ - public function importFile($file='', $category='_common_image', $opts = null, $new_data = array()) - { - $mes = e107::getMessage(); - $tp = e107::getParser(); - $sql = e107::getDb(); - - if(is_array($opts)) - { - $uploadPath = varset($opts['path']); - $oldpath = null; - } - else - { - $uploadPath = null; - $oldpath = $opts; - } - - if(empty($oldpath)) $oldpath = e_IMPORT.$file; - - if(!file_exists($oldpath)) - { - // Check it hasn't been imported already. - if($newpath = $this->checkDupe($oldpath, $file)) - { - $this->log("Line: ".__LINE__." Couldn't find the file: ".$oldpath); - return $newpath; - } - $this->log("Line: ".__LINE__." Couldn't find the file: ".$oldpath); - $mes->addError("Couldn't find the file: ".$oldpath); - return false; - } - - $img_data = $this->mediaData($oldpath); // Basic File Info only - - - if($category === '_icon') - { - $typePath = rtrim(e_MEDIA_ICON,'/'); - } - elseif(!$typePath = $this->getPath($img_data['media_type'], $uploadPath)) - { - $this->log("Line: ".__LINE__." Couldn't generate path from file info:".$oldpath); - $mes->addError("Couldn't generate path from file info:".$oldpath); - return false; - } - - - if(!$newpath = $this->checkDupe($oldpath,$typePath.'/'. $tp->filter($file,'file'))) - { - return $tp->createConstants($typePath.'/'.$file,'rel'); - } - - $newpath = $this->checkFileExtension($newpath, $img_data['media_type']); - - if(!rename($oldpath, $newpath)) // e_MEDIA.$newpath was working before. - { - $this->log("Couldn't move file from ".realpath($oldpath)." to ".e_MEDIA.$newpath); - $mes->add("Couldn't move file from ".$oldpath." to ".$newpath, E_MESSAGE_ERROR); - return false; - }; - - if($category === '_icon') // convert to _icon_16, _icon_32 etc. - { - $category = $this->getIconCategory($img_data); - } - - $img_data['media_url'] = $tp->createConstants($newpath,'rel'); - $img_data['media_name'] = $tp->toDB(basename($newpath)); - $img_data['media_caption'] = vartrue($new_data['media_caption']); - $img_data['media_category'] = vartrue($category,'_common_image'); - $img_data['media_description'] = vartrue($new_data['media_description']); - $img_data['media_userclass'] = '0'; - - if($sql->insert("core_media",$img_data)) - { - $mes->add("Importing Media: ".$file, E_MESSAGE_SUCCESS); - $this->log("Importing Media: ".$file." successful"); - return $img_data['media_url']; - } - else - { - $this->log("Db Insert Failed: ".var_export($img_data,true)); - rename($newpath,$oldpath); //move it back. - return false; - } - - - } - - - /** - * Calculate Icon Category from image meta data. - * @param array $img image meta data. - * @return string - */ - private function getIconCategory($img) - { - - if($img['media_type'] == 'image/svg+xml') - { - return "_icon_svg"; - } - - $sizes = array(16,32,48,64); - - $dimensions = $img['media_dimensions']; - - foreach($sizes as $dim) - { - list($w,$h) = explode(" x ", $dimensions); - - if($w == $dim || $h == $dim) - { - return "_icon_".$dim; - } - - } - - return "_icon_64"; // default. - - } - - - - - /** - * Check File-name against mime-type and add missing extension if necessary. - * @param $path - * @param $mime - * @return string - */ - public function checkFileExtension($path, $mime) - { - if(empty($mime)) - { - return $path; - } - - - $ext = e107::getFile()->getFileExtension($mime); - - if($ext && (substr($path,-4) != $ext)) - { - return $path.$ext; - } - else - { - return $path; - } - - } - - - private function browserCarouselItemSelector($data) - { - // $close = (E107_DEBUG_LEVEL > 0) ? "" : " data-close='true' "; // - // $select = (E107_DEBUG_LEVEL > 0) ? '' : " "; - $close = ''; - $select = ''; - - if(!empty($data['close']) && E107_DEBUG_LEVEL < 1) - { - $select .= "e-dialog-close"; - $close = " data-close='true' "; - } - - // e-dialog-save - - $style = varset($data['style'],''); - $class = varset($data['class'],''); - $dataPreview = !empty($data['previewHtml']) ? base64_encode($data['previewHtml']) : ''; - - $linkTag = ""; - - return $linkTag; - - } - - - function browserCarouselItem($row = array()) - { - $tp = e107::getParser(); - - $defaultThumb = $tp->thumbUrl('','w=400&h=240'); - - $default = array( - 'width' => 200, - 'height' => 113, - 'id' => '', - 'type' => 'image', - 'tagid' => '', - 'saveValue' => '', - 'previewUrl' => $defaultThumb , - 'previewHtml' => null, - 'thumbUrl' => $defaultThumb, - 'title' => '', - 'gridClass' => 'span2 col-md-2', - 'bbcode' => '', - 'tooltip' => '', - 'close' => true // close modal window after item selected - - ); - - $data = array(); - - foreach($default as $k=>$v) - { - $data[$k] = isset($row[$k]) ? $row[$k] : $default[$k]; - } - - - - - $text = "\n\n - - \n\n\n"; - - - - - return $text; - - } - - /** - * @param $slides - * @param $uniqueID - * @return string - */ - function browserIndicators($slides, $uniqueID) - { - - if(count($slides)<1) - { - return ''; - } - - $indicators = ''; - - return $indicators; - - } - - - - - /** - * Retriveve a Media-Manager thumbnail which was saved from a remote location. . - * @param $id - * @return bool|string - */ - function getThumb($id) - { - $id = trim($id); - $filename = 'temp/thumb-'.md5($id).".jpg"; - $filepath = e_MEDIA.$filename; - - if(file_exists($filepath)) - { - return e107::getParser()->createConstants($filepath); - } - - e107::getMessage()->addDebug("Couldn't find ".$filepath); - return false; - } - - - - /** - * Save a Media-Manager thumbnail from remote location. - * @param string $imageUrl - * @param string $id - * @return bool|string - */ - function saveThumb($imageUrl='',$id='') - { - - if(empty($id) || empty($imageUrl)) - { - return false; - } - - $filename = 'temp/thumb-'.md5($id).".jpg"; - $filepath = e_MEDIA.$filename; - - if(!file_exists($filepath)) - { - e107::getFile()->getRemoteFile($imageUrl, $filename,'media'); - } - - return $filepath; - } - - - /** - * Carousel Item Browser. - * @param array|string $data - array for items or string for an error alert. - * @param array $parm - * @return string - */ - function browserCarousel($data,$parm=null) - { - /* Fix for Bootstrap2 margin-left issue when wrapping */ - e107::css('inline',' - - - - .row-fluid .media-carousel.span6:nth-child(2n + 3) { margin-left : 0px; } - .row-fluid .media-carousel.span4:nth-child(3n + 4) { margin-left : 0px; } - .row-fluid .media-carousel.span3:nth-child(4n + 5) { margin-left : 0px; } - .row-fluid .media-carousel.span2:nth-child(6n + 7) { margin-left : 0px; } - '); - - // $frm = e107::getForm(); - - // $text .= print_a($_GET,true); - - $data_src = $this->mediaSelectNav($parm['category'], $parm['tagid'], $parm); - $carouselID = 'media-carousel-'.$parm['action']; - $searchToolttip = (empty($parm['searchTooltip'])) ? "Enter some text to filter results" : $parm['searchTooltip']; - //$text = "
"; -*/ -// LEGACY definition with LAN Shortcodes ({INFOTITLE})..... -$FORUM_MAIN_END = "\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
{INFOTITLE}
{LOGO}{USERINFO}
{INFO}
{FORUMINFO}
{USERLIST}
{STATLINK}
\n
\n
\n\n\n\n\n\n\n
{ICONKEY}{SEARCH}{PERMS}\n
\n
\n"; -} - -if (!isset($FORUM_NEWPOSTS_START)) -{ -// How it should be??? (LAN Shortcodes replaced by their outputed LANS...) -/* - $FORUM_NEWPOSTS_START = "
\n
\n\n\n\n\n\n"; -*/ -// LEGACY definition with LAN Shortcodes ({NEWTHREADTITLE}, {POSTEDTITLE})..... - $FORUM_NEWPOSTS_START = "
\n
\n
 ".LAN_FORUM_0075."".LAN_FORUM_0074."
\n\n\n\n\n"; -} - -if (!isset($FORUM_NEWPOSTS_MAIN)) -{ - $FORUM_NEWPOSTS_MAIN = "\n\n\n\n"; -} - -if (!isset($FORUM_NEWPOSTS_END)) -{ - $FORUM_NEWPOSTS_END = "
 {NEWTHREADTITLE}{POSTEDTITLE}
{NEWIMAGE}{NEWSPOSTNAME}{STARTERTITLE}
"; -} - -if (!isset($FORUM_TRACK_START)) -{ -// How it should be??? (LAN Shortcodes replaced by their outputed LANS...) -/* - $FORUM_TRACK_START = "
\n
\n\n\n\n\n"; -*/ -// LEGACY definition with LAN Shortcodes ({TRACKTITLE})..... -$FORUM_TRACK_START = "
\n
\n
".LAN_FORUM_0073."
\n\n\n\n"; - - if (!isset($FORUM_TRACK_MAIN)) - { - $FORUM_TRACK_MAIN = " - - - - "; - } -} - -if (!isset($FORUM_TRACK_END)) -{ - $FORUM_TRACK_END = "
{TRACKTITLE}
{NEWIMAGE}{TRACKPOSTNAME}{UNTRACK}
\n
\n
"; -} - - -/* -$FORUM_MAIN_START = "
MAIN START"; -$FORUM_MAIN_PARENT = "
MAIN PARENT"; -$FORUM_MAIN_FORUM = "
MAIN FORUM"; -$FORUM_MAIN_END = "
MAIN END"; -$FORUM_NEWPOSTS_START = "
NEWPOSTS-START"; -$FORUM_NEWPOSTS_MAIN = "
NEWPOSTS-MAIN"; -$FORUM_NEWPOSTS_END = "
NEWPOSTS END"; -$FORUM_TRACK_START = "
TRACK-START"; -$FORUM_TRACK_MAIN = "
TRACK-MAIN"; -$FORUM_TRACK_END = "
TRACK-END"; -*/ - -// New in v2.x - requires a bootstrap theme be loaded. - - -$FORUM_TEMPLATE['main']['start'] = "{FORUM_BREADCRUMB} -
- -
- {SEARCH} -
-
-
- - - - - - - - - - - "; - -$FORUM_TEMPLATE['main']['parent'] = " - - - - - "; - - - -$FORUM_TEMPLATE['main']['forum'] = " - - - - - - "; - -//{LASTPOST:type=username} + {LASTPOST:type=datelink} can also be replaced by the legacy shortcodes {LASTPOST} or {LASTPOSTUSER} + {LASTPOSTDATE} - -$FORUM_TEMPLATE['main']['end'] = "
{FORUMTITLE}
{PARENTIMAGE:h=50}{PARENTNAME} {PARENTSTATUS}".LAN_FORUM_0002."
{NEWFLAG}{FORUMIMAGE:h=50}{FORUMNAME}
{FORUMDESCRIPTION}{FORUMSUBFORUMS}
{THREADSX}
"; - -// $FORUM_WRAPPER['main']['forum']['USERINFOX'] = "{FORUM_BREADCRUMB}(html before){---}(html after)"; - -// Tracking -$FORUM_TEMPLATE['track']['start'] = "{FORUM_BREADCRUMB}
- - - - - - - - - - - - - - - - "; - -$FORUM_TEMPLATE['track']['item'] = " - - - - - "; - - -$FORUM_TEMPLATE['track']['end'] = "
".LAN_FORUM_1003."".LAN_FORUM_1020."
{NEWIMAGE}{TRACKPOSTNAME}{UNTRACK}
\n
"; - - - - -/* -$FORUM_TEMPLATE['main-end'] .= " - -
- {PERMS} -
-\n -\n\n - -\n -\n\n -\n\n -\n\n\n
{INFOTITLE}
{LOGO}{USERINFO}
{INFO}
{FORUMINFO}
{USERLIST}
{STATLINK}
-"; -*/ -?> +\n
\n\n\n\n\n\n\n"; +*/ +// LEGACY definition with LAN Shortcodes ({THREADTITLE}, {REPLYTITLE}, {LASTPOSTITLE})..... + $FORUM_MAIN_START = "
\n
\n
{FORUMTITLE}".LAN_FORUM_0002."".LAN_FORUM_0003."".LAN_FORUM_0004."
\n\n\n\n\n\n"; +} +if (!isset($FORUM_MAIN_PARENT)) +{ + $FORUM_MAIN_PARENT = " \n\n"; +} +if (!isset($FORUM_MAIN_FORUM)) +{ + $SC_WRAPPER['LASTPOST:type=date'] = "{---}
"; + $SC_WRAPPER['LASTPOST:type=url'] = " ".IMAGE_post2.""; + $FORUM_MAIN_FORUM = "\n\n\n\n\n\n"; +} +if (!isset($FORUM_MAIN_END)) +{ +// How it should be??? (LAN Shortcodes replaced by their outputed LANS...) +/* + $FORUM_MAIN_END = "
{FORUMTITLE}{THREADTITLE}{REPLYTITLE}{LASTPOSTITLE}
{PARENTNAME} {PARENTSTATUS}
{NEWFLAG}{FORUMNAME}
{FORUMDESCRIPTION}{FORUMSUBFORUMS}
{THREADS}{REPLIES}{LASTPOST}
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
".LAN_FORUM_0009."
{LOGO}{USERINFO}
{INFO}
{FORUMINFO}
{USERLIST}
{STATLINK}
\n
\n
\n\n\n\n\n\n\n
{ICONKEY}{SEARCH}{PERMS}\n
\n
\n"; +*/ +// LEGACY definition with LAN Shortcodes ({INFOTITLE})..... +$FORUM_MAIN_END = "\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
{INFOTITLE}
{LOGO}{USERINFO}
{INFO}
{FORUMINFO}
{USERLIST}
{STATLINK}
\n
\n
\n\n\n\n\n\n\n
{ICONKEY}{SEARCH}{PERMS}\n
\n
\n"; +} + +if (!isset($FORUM_NEWPOSTS_START)) +{ +// How it should be??? (LAN Shortcodes replaced by their outputed LANS...) +/* + $FORUM_NEWPOSTS_START = "
\n
\n\n\n\n\n\n"; +*/ +// LEGACY definition with LAN Shortcodes ({NEWTHREADTITLE}, {POSTEDTITLE})..... + $FORUM_NEWPOSTS_START = "
\n
\n
 ".LAN_FORUM_0075."".LAN_FORUM_0074."
\n\n\n\n\n"; +} + +if (!isset($FORUM_NEWPOSTS_MAIN)) +{ + $FORUM_NEWPOSTS_MAIN = "\n\n\n\n"; +} + +if (!isset($FORUM_NEWPOSTS_END)) +{ + $FORUM_NEWPOSTS_END = "
 {NEWTHREADTITLE}{POSTEDTITLE}
{NEWIMAGE}{NEWSPOSTNAME}{STARTERTITLE}
"; +} + +if (!isset($FORUM_TRACK_START)) +{ +// How it should be??? (LAN Shortcodes replaced by their outputed LANS...) +/* + $FORUM_TRACK_START = "
\n
\n\n\n\n\n"; +*/ +// LEGACY definition with LAN Shortcodes ({TRACKTITLE})..... +$FORUM_TRACK_START = "
\n
\n
".LAN_FORUM_0073."
\n\n\n\n"; + + if (!isset($FORUM_TRACK_MAIN)) + { + $FORUM_TRACK_MAIN = " + + + + "; + } +} + +if (!isset($FORUM_TRACK_END)) +{ + $FORUM_TRACK_END = "
{TRACKTITLE}
{NEWIMAGE}{TRACKPOSTNAME}{UNTRACK}
\n
\n
"; +} + + +/* +$FORUM_MAIN_START = "
MAIN START"; +$FORUM_MAIN_PARENT = "
MAIN PARENT"; +$FORUM_MAIN_FORUM = "
MAIN FORUM"; +$FORUM_MAIN_END = "
MAIN END"; +$FORUM_NEWPOSTS_START = "
NEWPOSTS-START"; +$FORUM_NEWPOSTS_MAIN = "
NEWPOSTS-MAIN"; +$FORUM_NEWPOSTS_END = "
NEWPOSTS END"; +$FORUM_TRACK_START = "
TRACK-START"; +$FORUM_TRACK_MAIN = "
TRACK-MAIN"; +$FORUM_TRACK_END = "
TRACK-END"; +*/ + +// New in v2.x - requires a bootstrap theme be loaded. + + +$FORUM_TEMPLATE['main']['start'] = "{FORUM_BREADCRUMB} +
+ +
+ {SEARCH} +
+
+
+ + + + + + + + + + + "; + +$FORUM_TEMPLATE['main']['parent'] = " + + + + + "; + + + +$FORUM_TEMPLATE['main']['forum'] = " + + + + + + "; + +//{LASTPOST:type=username} + {LASTPOST:type=datelink} can also be replaced by the legacy shortcodes {LASTPOST} or {LASTPOSTUSER} + {LASTPOSTDATE} + +$FORUM_TEMPLATE['main']['end'] = "
{FORUMTITLE}
{PARENTIMAGE:h=50}{PARENTNAME} {PARENTSTATUS}".LAN_FORUM_0002."
{NEWFLAG}{FORUMIMAGE:h=50}{FORUMNAME}
{FORUMDESCRIPTION}{FORUMSUBFORUMS}
{THREADSX}
"; + +// $FORUM_WRAPPER['main']['forum']['USERINFOX'] = "{FORUM_BREADCRUMB}(html before){---}(html after)"; + +// Tracking +$FORUM_TEMPLATE['track']['start'] = "{FORUM_BREADCRUMB}
+ + + + + + + + + + + + + + + + "; + +$FORUM_TEMPLATE['track']['item'] = " + + + + + "; + + +$FORUM_TEMPLATE['track']['end'] = "
".LAN_FORUM_1003."".LAN_FORUM_1020."
{NEWIMAGE}{TRACKPOSTNAME}{UNTRACK}
\n
"; + + + + +/* +$FORUM_TEMPLATE['main-end'] .= " + +
+ {PERMS} +
+\n +\n\n + +\n +\n\n +\n\n +\n\n\n
{INFOTITLE}
{LOGO}{USERINFO}
{INFO}
{FORUMINFO}
{USERLIST}
{STATLINK}
+"; +*/ +?> diff --git a/e107_plugins/gallery/controllers/index.php b/e107_plugins/gallery/controllers/index.php index b73ccbef5..c511d3c4e 100644 --- a/e107_plugins/gallery/controllers/index.php +++ b/e107_plugins/gallery/controllers/index.php @@ -1,233 +1,233 @@ - array(var => validationArray) - * @var array - */ - protected $filter = array( - 'category' => array( - 'cat' => array('regex', '/[\w\pL\s\-+.,]+/u'), - ), - 'list' => array( - 'cat' => array('regex', '/[\w\pL\s\-+.,]+/u'), - 'frm' => array('int'), - ), - ); - - /** - * @var array - */ - protected $catList; - - public function init() - { - e107::plugLan('gallery', 'front'); - e107::css('gallery', 'css/gallery.css'); - $this->catList = e107::getMedia()->getCategories('gallery'); - } - - public function actionIndex() - { - if(isset($_GET['cat']) && !empty($_GET['cat'])) - { - $this->_forward('list'); - } - else - { - $this->_forward('category'); - } - } - - - private function getTemplate() - { - $template = e107::getTemplate('gallery'); - - $oldKeys = array( - 'list_start', 'list_item', 'list_caption', 'list_end', - 'cat_start', 'cat_item', 'cat_caption', 'cat_end' - ); - - if(isset($template['list_start'])) - { - foreach($oldKeys as $k) - { - list($main,$sub) = explode("_",$k); - $template[$main][$sub] = $template[$k]; - unset($template[$k]); - - } - - - } - - return $template; - } - - - - public function actionCategory() - { - // print_a("Hi there"); - - $template = $this->getTemplate(); - $template = array_change_key_case($template); - $sc = e107::getScBatch('gallery', true); - - $text = ""; - - if(defset('BOOTSTRAP') === true || defset('BOOTSTRAP') === 2) // Convert bootsrap3 to bootstrap2 compat. - { - $template['cat_start'] = str_replace('row', 'row-fluid', $template['cat_start']); - } - - $text = e107::getParser()->parseTemplate($template['cat']['start'], true, $sc); - - foreach($this->catList as $val) - { - $sc->setVars($val); - $text .= e107::getParser()->parseTemplate($template['cat']['item'], true); - } - - $text .= e107::getParser()->parseTemplate($template['cat']['end'], true, $sc); - - if(isset($template['cat']['caption'])) - { - $title = e107::getParser()->parseTemplate($template['cat']['caption'], true, $sc); - - $this->addTitle($title)->addBody($text); - } - else - { - $this->addTitle(LAN_PLUGIN_GALLERY_TITLE)->addBody($text); - } - - - } - - public function actionList() - { - $plugPrefs = e107::getPlugConfig('gallery')->getPref(); - - $request = $this->getRequest(); - - // use only filtered variables - $cid = $request->getRequestParam('cat'); - - if($cid && !isset($this->catList[$cid])) - { - // get ID by SEF - $_cid = null; - foreach($this->catList as $id => $row) - { - if($cid === $row['media_cat_sef']) - { - $_cid = $id; - break; - } - } - $cid = $_cid; - } - - if(empty($cid) || !isset($this->catList[$cid])) - { - $this->_forward('category'); - return; - } - - $tp = e107::getParser(); - $template = $this->getTemplate(); - $template = array_change_key_case($template); - - $sc = e107::getScBatch('gallery', true); - - if(defset('BOOTSTRAP') === true || defset('BOOTSTRAP') === 2) // Convert bootsrap3 to bootstrap2 compat. - { - $template['list_start'] = str_replace('row', 'row-fluid', $template['list_start']); - } - - $sc->total = e107::getMedia()->countImages($cid); - $sc->amount = varset($plugPrefs['perpage'], 12); - $sc->curCat = $cid; - $sc->from = $request->getRequestParam('frm', 0); - - $orderBy = varset($plugPrefs['orderby'], 'media_id DESC'); - - $list = e107::getMedia()->getImages($cid, $sc->from, $sc->amount, null, $orderBy); - $catname = $tp->toHTML($this->catList[$cid]['media_cat_title'], false, 'defs'); - $cat = $this->catList[$cid]; - - $inner = ""; - - foreach($list as $row) - { - $sc->setVars($row) - ->addVars($cat); - - $inner .= $tp->parseTemplate($template['list']['item'], true, $sc); - } - - $text = $tp->parseTemplate($template['list']['start'], true, $sc); - $text .= $inner; - $text .= $tp->parseTemplate($template['list']['end'], true, $sc); - - if(isset($template['list']['caption'])) - { - $title = $tp->parseTemplate($template['list']['caption'], true, $sc); - $this->addTitle($title)->addBody($text); - } - else - { - $this->addTitle(LAN_PLUGIN_GALLERY_TITLE) - ->addTitle($catname) - ->addBody($text); - } - - } -} + array(var => validationArray) + * @var array + */ + protected $filter = array( + 'category' => array( + 'cat' => array('regex', '/[\w\pL\s\-+.,]+/u'), + ), + 'list' => array( + 'cat' => array('regex', '/[\w\pL\s\-+.,]+/u'), + 'frm' => array('int'), + ), + ); + + /** + * @var array + */ + protected $catList; + + public function init() + { + e107::plugLan('gallery', 'front'); + e107::css('gallery', 'css/gallery.css'); + $this->catList = e107::getMedia()->getCategories('gallery'); + } + + public function actionIndex() + { + if(isset($_GET['cat']) && !empty($_GET['cat'])) + { + $this->_forward('list'); + } + else + { + $this->_forward('category'); + } + } + + + private function getTemplate() + { + $template = e107::getTemplate('gallery'); + + $oldKeys = array( + 'list_start', 'list_item', 'list_caption', 'list_end', + 'cat_start', 'cat_item', 'cat_caption', 'cat_end' + ); + + if(isset($template['list_start'])) + { + foreach($oldKeys as $k) + { + list($main,$sub) = explode("_",$k); + $template[$main][$sub] = $template[$k]; + unset($template[$k]); + + } + + + } + + return $template; + } + + + + public function actionCategory() + { + // print_a("Hi there"); + + $template = $this->getTemplate(); + $template = array_change_key_case($template); + $sc = e107::getScBatch('gallery', true); + + $text = ""; + + if(defset('BOOTSTRAP') === true || defset('BOOTSTRAP') === 2) // Convert bootsrap3 to bootstrap2 compat. + { + $template['cat_start'] = str_replace('row', 'row-fluid', $template['cat_start']); + } + + $text = e107::getParser()->parseTemplate($template['cat']['start'], true, $sc); + + foreach($this->catList as $val) + { + $sc->setVars($val); + $text .= e107::getParser()->parseTemplate($template['cat']['item'], true); + } + + $text .= e107::getParser()->parseTemplate($template['cat']['end'], true, $sc); + + if(isset($template['cat']['caption'])) + { + $title = e107::getParser()->parseTemplate($template['cat']['caption'], true, $sc); + + $this->addTitle($title)->addBody($text); + } + else + { + $this->addTitle(LAN_PLUGIN_GALLERY_TITLE)->addBody($text); + } + + + } + + public function actionList() + { + $plugPrefs = e107::getPlugConfig('gallery')->getPref(); + + $request = $this->getRequest(); + + // use only filtered variables + $cid = $request->getRequestParam('cat'); + + if($cid && !isset($this->catList[$cid])) + { + // get ID by SEF + $_cid = null; + foreach($this->catList as $id => $row) + { + if($cid === $row['media_cat_sef']) + { + $_cid = $id; + break; + } + } + $cid = $_cid; + } + + if(empty($cid) || !isset($this->catList[$cid])) + { + $this->_forward('category'); + return; + } + + $tp = e107::getParser(); + $template = $this->getTemplate(); + $template = array_change_key_case($template); + + $sc = e107::getScBatch('gallery', true); + + if(defset('BOOTSTRAP') === true || defset('BOOTSTRAP') === 2) // Convert bootsrap3 to bootstrap2 compat. + { + $template['list_start'] = str_replace('row', 'row-fluid', $template['list_start']); + } + + $sc->total = e107::getMedia()->countImages($cid); + $sc->amount = varset($plugPrefs['perpage'], 12); + $sc->curCat = $cid; + $sc->from = $request->getRequestParam('frm', 0); + + $orderBy = varset($plugPrefs['orderby'], 'media_id DESC'); + + $list = e107::getMedia()->getImages($cid, $sc->from, $sc->amount, null, $orderBy); + $catname = $tp->toHTML($this->catList[$cid]['media_cat_title'], false, 'defs'); + $cat = $this->catList[$cid]; + + $inner = ""; + + foreach($list as $row) + { + $sc->setVars($row) + ->addVars($cat); + + $inner .= $tp->parseTemplate($template['list']['item'], true, $sc); + } + + $text = $tp->parseTemplate($template['list']['start'], true, $sc); + $text .= $inner; + $text .= $tp->parseTemplate($template['list']['end'], true, $sc); + + if(isset($template['list']['caption'])) + { + $title = $tp->parseTemplate($template['list']['caption'], true, $sc); + $this->addTitle($title)->addBody($text); + } + else + { + $this->addTitle(LAN_PLUGIN_GALLERY_TITLE) + ->addTitle($catname) + ->addBody($text); + } + + } +} \ No newline at end of file diff --git a/e107_plugins/gallery/css/gallery.css b/e107_plugins/gallery/css/gallery.css index b016f4882..b7b5df11c 100644 --- a/e107_plugins/gallery/css/gallery.css +++ b/e107_plugins/gallery/css/gallery.css @@ -1,55 +1,55 @@ - - - -/* IMAGE LIST */ - -ul.gallery > li > div > h5 { text-align: center } -ul.gallery-cat > li > div > h3 { text-align: center } - -/* CATEGORY LIST */ - - - -.lb-dataContainer { padding-top:10px; font-size: 110%;} - -.lb-caption { } - - -/* SLIDESHOW */ - -#gallery-slideshow-wrapper { display:block; -webkit-border-radius:5px; -moz-border-radius:5px; border-radius:5px; width: 664px; height: 146px; overflow: hidden; background: #000000; margin-left:auto;margin-right:auto; max-width:100% } - -#gallery-slideshow-content { width: 3500px; } - -#gallery-slideshow-content .slide { float: left; width: 679px; padding:12px; height: 146px; white-space:nowrap } - -.gallery-slideshow-controls { clear:both; width: 664px; margin-left:auto; margin-right:auto; padding-top:5px; padding-bottom:10px; max-width:100%; } - -.gallery-slide-item { margin-right:8px; display: inline-block; } - -.gallery-slideshow-thumb { -webkit-border-radius:5px; -moz-border-radius:5px; border-radius:5px; } - -.gallery-slideshow-thumb:hover { } - -.gallery-slide-jumper-container { text-align:center; padding-left:250px;} - -.gallery-slide-jumper { padding:3px;} - -.gallery-slide-jumper-selected { font-weight:bold } - - -/* Fix for Bootstrap2 margin-left issue when wrapping */ -.row-fluid .gallery div.span6:nth-child(2n + 3) { margin-left : 0px; } -.row-fluid .gallery div.span4:nth-child(3n + 4) { margin-left : 0px; } -.row-fluid .gallery div.span3:nth-child(4n + 5) { margin-left : 0px; } -.row-fluid .gallery div.span2:nth-child(6n + 7) { margin-left : 0px; } - -.row-fluid .gallery-cat div.span6:nth-child(2n + 3) { margin-left : 0px; } -.row-fluid .gallery-cat div.span4:nth-child(3n + 4) { margin-left : 0px; } -.row-fluid .gallery-cat div.span3:nth-child(4n + 5) { margin-left : 0px; } -.row-fluid .gallery-cat div.span2:nth-child(6n + 7) { margin-left : 0px; } - -/* Work-around for indent issue. see: https://github.com/twitter/bootstrap/issues/4890 */ -.thumbnails .span2:nth-child(6n+1) { - margin-left:0; -} + + + +/* IMAGE LIST */ + +ul.gallery > li > div > h5 { text-align: center } +ul.gallery-cat > li > div > h3 { text-align: center } + +/* CATEGORY LIST */ + + + +.lb-dataContainer { padding-top:10px; font-size: 110%;} + +.lb-caption { } + + +/* SLIDESHOW */ + +#gallery-slideshow-wrapper { display:block; -webkit-border-radius:5px; -moz-border-radius:5px; border-radius:5px; width: 664px; height: 146px; overflow: hidden; background: #000000; margin-left:auto;margin-right:auto; max-width:100% } + +#gallery-slideshow-content { width: 3500px; } + +#gallery-slideshow-content .slide { float: left; width: 679px; padding:12px; height: 146px; white-space:nowrap } + +.gallery-slideshow-controls { clear:both; width: 664px; margin-left:auto; margin-right:auto; padding-top:5px; padding-bottom:10px; max-width:100%; } + +.gallery-slide-item { margin-right:8px; display: inline-block; } + +.gallery-slideshow-thumb { -webkit-border-radius:5px; -moz-border-radius:5px; border-radius:5px; } + +.gallery-slideshow-thumb:hover { } + +.gallery-slide-jumper-container { text-align:center; padding-left:250px;} + +.gallery-slide-jumper { padding:3px;} + +.gallery-slide-jumper-selected { font-weight:bold } + + +/* Fix for Bootstrap2 margin-left issue when wrapping */ +.row-fluid .gallery div.span6:nth-child(2n + 3) { margin-left : 0px; } +.row-fluid .gallery div.span4:nth-child(3n + 4) { margin-left : 0px; } +.row-fluid .gallery div.span3:nth-child(4n + 5) { margin-left : 0px; } +.row-fluid .gallery div.span2:nth-child(6n + 7) { margin-left : 0px; } + +.row-fluid .gallery-cat div.span6:nth-child(2n + 3) { margin-left : 0px; } +.row-fluid .gallery-cat div.span4:nth-child(3n + 4) { margin-left : 0px; } +.row-fluid .gallery-cat div.span3:nth-child(4n + 5) { margin-left : 0px; } +.row-fluid .gallery-cat div.span2:nth-child(6n + 7) { margin-left : 0px; } + +/* Work-around for indent issue. see: https://github.com/twitter/bootstrap/issues/4890 */ +.thumbnails .span2:nth-child(6n+1) { + margin-left:0; +} diff --git a/e107_plugins/gallery/e_header.php b/e107_plugins/gallery/e_header.php index a07192ab2..9122440a6 100644 --- a/e107_plugins/gallery/e_header.php +++ b/e107_plugins/gallery/e_header.php @@ -1,33 +1,33 @@ -getPref(); - - if(vartrue($plugPrefs['pp_global'], false)) - { - e107_require_once(e_PLUGIN . 'gallery/includes/gallery_load.php'); - // Load prettyPhoto settings and files. - gallery_load_prettyphoto(); - } - -} +getPref(); + + if(vartrue($plugPrefs['pp_global'], false)) + { + e107_require_once(e_PLUGIN . 'gallery/includes/gallery_load.php'); + // Load prettyPhoto settings and files. + gallery_load_prettyphoto(); + } + +} diff --git a/e107_plugins/gallery/e_shortcode.php b/e107_plugins/gallery/e_shortcode.php index a448cba31..e1c69f551 100644 --- a/e107_plugins/gallery/e_shortcode.php +++ b/e107_plugins/gallery/e_shortcode.php @@ -1,360 +1,360 @@ -attFull = array('w' => $pop_w, 'h' => $pop_h, 'x' => 1, 'crop' => 0); // 'w='.$pop_w.'&h='.$pop_h.'&x=1'; - } - - function sc_gallery_caption($parm = '') - { - $tp = e107::getParser(); - - if($parm === 'text') - { - return $tp->toAttribute($this->var['media_caption']); - } - - - e107_require_once(e_PLUGIN . 'gallery/includes/gallery_load.php'); - // Load prettyPhoto settings and files. - gallery_load_prettyphoto(); - - $plugPrefs = e107::getPlugConfig('gallery')->getPref(); - $hook = varset($plugPrefs['pp_hook'], 'data-gal'); - - $text = "attFull) . "' " . $hook . "='prettyPhoto[slide]' >"; // Erase rel"lightbox.Gallery2" - Write "prettyPhoto[slide]" - $text .= $this->var['media_caption']; - $text .= ""; - return $text; - } - - function sc_gallery_description($parm = '') - { - $tp = e107::getParser(); - return $tp->toHTML($this->var['media_description'], true, 'BODY'); - } - - function sc_gallery_breadcrumb($parm = '') - { - $breadcrumb = array(); - - $template = e107::getTemplate('gallery', 'gallery', 'cat'); - - $caption = isset($template['caption']) ? e107::getParser()->toText($template['caption']) : LAN_PLUGIN_GALLERY_TITLE; - - $breadcrumb[] = array('text' => $caption, 'url' => e107::getUrl()->create('gallery', $this->var)); - - if(vartrue($this->curCat)) - { - $breadcrumb[] = array('text' => $this->sc_gallery_cat_title('title'), 'url' => e107::getUrl()->create('gallery/index/list', $this->var)); - } - - return e107::getForm()->breadcrumb($breadcrumb); - } - - /** - * All possible parameters - * {GALLERY_THUMB=w=200&h=200&thumburl&thumbsrc&imageurl&orig} - * w and h - optional width and height of the thumbnail - * thumburl - return only the URL of the destination image (large one) - * thumbsrc - url to the thumb, as it's written in the src attribute of the image - * imageurl - full path to the destination image (no proxy) - * actualPreview - large preview will use the original path to the image (no proxy) - */ - function sc_gallery_thumb($parm = '') - { - e107_require_once(e_PLUGIN . 'gallery/includes/gallery_load.php'); - // Load prettyPhoto settings and files. - gallery_load_prettyphoto(); - - $plugPrefs = e107::getPlugConfig('gallery')->getPref(); - $hook = varset($plugPrefs['pp_hook'], 'data-gal'); - - $tp = e107::getParser(); - $parms = eHelper::scParams($parm); - - $w = vartrue($parms['w']) ? $parms['w'] : $tp->thumbWidth(); // 190; // 160; - $h = vartrue($parms['h']) ? $parms['h'] : $tp->thumbHeight(); // 130; - - $class = ($this->slideMode == true) ? 'gallery-slideshow-thumb img-responsive img-fluid img-rounded rounded' : varset($parms['class'], 'gallery-thumb img-responsive img-fluid'); - $rel = ($this->slideMode == true) ? 'prettyPhoto[pp_gal]' : 'prettyPhoto[pp_gal]'; - - //$att = array('aw'=>$w, 'ah'=>$h, 'x'=>1, 'crop'=>1); - $caption = $tp->toAttribute($this->var['media_caption']); - $att = array('w' => $w, 'h' => $h, 'class' => $class, 'alt' => $caption, 'x' => 1, 'crop' => 1); - - - $srcFull = $tp->thumbUrl($this->var['media_url'], $this->attFull); - - if(vartrue($parms['actualPreview'])) - { - $srcFull = $tp->replaceConstants($this->var['media_url'], 'full'); - } - - if(isset($parms['thumburl'])) - { - return $srcFull; - } - elseif(isset($parms['thumbsrc'])) - { - return $tp->thumbUrl($this->var['media_url'], $att); - } - elseif(isset($parms['imageurl'])) - { - return $tp->replaceConstants($this->var['media_url'], 'full'); - } - - $description = $tp->toAttribute($this->var['media_description']); - - $text = ""; - $text .= $tp->toImage($this->var['media_url'], $att); - $text .= ""; - - return $text; - } - - function sc_gallery_cat_title($parm = '') - { - $tp = e107::getParser(); - $url = e107::getUrl()->create('gallery/index/list', $this->var); - if($parm == 'title') - { - return $tp->toHTML($this->var['media_cat_title'], false, 'TITLE'); - } - $text = ""; - $text .= $tp->toHTML($this->var['media_cat_title'], false, 'TITLE'); - $text .= ""; - return $text; - } - - function sc_gallery_cat_url($parm = '') - { - return e107::getUrl()->create('gallery/index/list', $this->var); - } - - function sc_gallery_cat_description($parm = '') - { - $tp = e107::getParser(); - return $tp->toHTML($this->var['media_cat_diz'], true, 'BODY'); - } - - function sc_gallery_baseurl() - { - return e107::getUrl()->create('gallery'); - } - - function sc_gallery_cat_thumb($parm = '') - { - $parms = eHelper::scParams($parm); - - $w = vartrue($parms['w']) ? $parms['w'] : 300; // 260; - $h = vartrue($parms['h']) ? $parms['h'] : 200; // 180; - $att = 'aw=' . $w . '&ah=' . $h . '&x=1'; // 'aw=190&ah=150'; - - $url = e107::getUrl()->create('gallery/index/list', $this->var); - - if(isset($parms['thumbsrc'])) - { - return e107::getParser()->thumbUrl($this->var['media_cat_image'], $att); - } - - $text = ""; - $text .= ""; - $text .= ""; - return $text; - } - - function sc_gallery_nextprev($parm = '') - { - // we passs both fields, the router will convert one of them to 'cat' variable, based on the current URL config - $url = 'route::gallery/index/list?media_cat_category=' . $this->curCat . '--AMP--media_cat_sef=' . $this->var['media_cat_sef'] . '--AMP--frm=--FROM--::full=1'; - $parm = 'total=' . $this->total . '&amount=' . $this->amount . '¤t=' . $this->from . '&url=' . rawurlencode($url); // .'&url='.$url; - $text = e107::getParser()->parseTemplate("{NEXTPREV=" . $parm . "}"); - return $text; - } - - function sc_gallery_slideshow($parm = '') - { - $this->sliderCat = ($parm) ? $parm : vartrue(e107::getPlugPref('gallery', 'slideshow_category'), 1); - - $tmpl = e107::getTemplate('gallery', 'gallery'); - $template = array_change_key_case($tmpl); - - return e107::getParser()->parseTemplate($template['slideshow_wrapper']); - } - - /** - * Display a Grid of thumbnails - useful for home pages. - * Amount per row differs according to device, so they are not set here, only the amount. - * @example {GALLERY_PORTFOLIO: placeholder=1&category=2} - */ - function sc_gallery_portfolio($parm=null) - { - $ns = e107::getRender(); - $tp = e107::getParser(); - // $parm = eHelper::scParams($parms); - $cat = (!empty($parm['category'])) ? $parm['category'] : vartrue(e107::getPlugPref('gallery', 'slideshow_category'), false); //TODO Separate pref? - - $tmpl = e107::getTemplate('gallery', 'gallery'); - $limit = vartrue($parm['limit'], 6); - - $plugPrefs = e107::getPlugConfig('gallery')->getPref(); - $orderBy = varset($plugPrefs['orderby'], 'media_id DESC'); - - $imageQry = (empty($cat) || $cat==1) ? "gallery_image|gallery_image_1|gallery_1" : 'gallery_' . $cat . '|gallery_image_' . $cat; - - - - $list = e107::getMedia()->getImages($imageQry, 0, $limit, null, $orderBy); - - if(count($list) < 1 && vartrue($parm['placeholder'])) - { - $list = array(); - - for($i = 0; $i < $limit; $i++) - { - $list[] = array('media_url' => ''); - } - } - - $template = e107::getTemplate('gallery', 'gallery', 'portfolio'); - - if(!empty($template['start'])) - { - $text = $tp->parseTemplate($template['start'],true, $this); - } - else - { - $text = ''; - } - - //NOTE: Using tablerender() allows the theme developer to set the number of columns etc using col-xx-xx - - foreach($list as $val) - { - $this->var = $val; - - if(empty($template['item'])) - { - $text .= $ns->tablerender('', $this->sc_gallery_thumb('class=gallery_thumb img-responsive img-fluid img-home-portfolio'), 'gallery_portfolio', true); - } - else - { - $text .= $tp->parseTemplate($template['item'],true,$this); - } - - } - - if(!empty($template['end'])) - { - $text .= $tp->parseTemplate($template['end'],true, $this); - } - - return $text; - - } - - - /** - * All possible parameters - * {GALLERY_SLIDES=4|limit=16&template=MY_SLIDESHOW_SLIDE_ITEM} - * first parameter is always number of slides, default is 3 - * limit - (optional) total limit of pcitures to be shown - * template - (optional) template - name of template to be used for parsing the slideshow item - */ - function sc_gallery_slides($parm) - { - $plugPrefs = e107::getPlugConfig('gallery')->getPref(); - $orderBy = varset($plugPrefs['orderby'], 'media_id DESC'); - - $tp = e107::getParser(); - $this->slideMode = true; - $parms = eHelper::scDualParams($parm); - $amount = $parms[1] ? intval($parms[1]) : 3; // vartrue(e107::getPlugPref('gallery','slideshow_perslide'),3); - $parms = $parms[2]; - $limit = (integer) vartrue($parms['limit'], 16); - $list = e107::getMedia()->getImages('gallery_image|gallery_' . $this->sliderCat . '|gallery_image_' . $this->sliderCat, 0, $limit, null, $orderBy); - $tmpl = e107::getTemplate('gallery', 'gallery'); - $tmpl = array_change_key_case($tmpl); // change template key to lowercase (BC fix) - $tmpl_key = vartrue($parms['template'], 'slideshow_slide_item'); - $item_template = $tmpl[$tmpl_key]; // e107::getTemplate('gallery','gallery', vartrue($parms['template'], 'SLIDESHOW_SLIDE_ITEM')); - $catList = e107::getMedia()->getCategories('gallery'); - $cat = $catList['gallery_' . $this->sliderCat]; - - $count = 1; - $inner = ''; - foreach($list as $row) - { - $this->setVars($row) - ->addVars($cat); - - $inner .= ($count == 1) ? "\n\n\n\n\n" : ""; - - if($count == $amount) - { - $count = 1; - $this->slideCount++; - } - else - { - $count++; - } - } - - $inner .= ($count != 1) ? "" : ""; - return $inner; - } - - - function sc_gallery_jumper($parm) - { - // echo "SlideCount=".$this->slideCount; - if($this->slideCount == 1 && deftrue('E107_DBG_BASIC')) - { - return "gallery-jumper must be loaded after Gallery-Slides"; - } - - $text = ''; - for($i = 1; $i < ($this->slideCount); $i++) - { - $val = ($parm == 'space') ? " " : $i; - $text .= '' . $val . ''; - } - - return $text; - - } -} +attFull = array('w' => $pop_w, 'h' => $pop_h, 'x' => 1, 'crop' => 0); // 'w='.$pop_w.'&h='.$pop_h.'&x=1'; + } + + function sc_gallery_caption($parm = '') + { + $tp = e107::getParser(); + + if($parm === 'text') + { + return $tp->toAttribute($this->var['media_caption']); + } + + + e107_require_once(e_PLUGIN . 'gallery/includes/gallery_load.php'); + // Load prettyPhoto settings and files. + gallery_load_prettyphoto(); + + $plugPrefs = e107::getPlugConfig('gallery')->getPref(); + $hook = varset($plugPrefs['pp_hook'], 'data-gal'); + + $text = "attFull) . "' " . $hook . "='prettyPhoto[slide]' >"; // Erase rel"lightbox.Gallery2" - Write "prettyPhoto[slide]" + $text .= $this->var['media_caption']; + $text .= ""; + return $text; + } + + function sc_gallery_description($parm = '') + { + $tp = e107::getParser(); + return $tp->toHTML($this->var['media_description'], true, 'BODY'); + } + + function sc_gallery_breadcrumb($parm = '') + { + $breadcrumb = array(); + + $template = e107::getTemplate('gallery', 'gallery', 'cat'); + + $caption = isset($template['caption']) ? e107::getParser()->toText($template['caption']) : LAN_PLUGIN_GALLERY_TITLE; + + $breadcrumb[] = array('text' => $caption, 'url' => e107::getUrl()->create('gallery', $this->var)); + + if(vartrue($this->curCat)) + { + $breadcrumb[] = array('text' => $this->sc_gallery_cat_title('title'), 'url' => e107::getUrl()->create('gallery/index/list', $this->var)); + } + + return e107::getForm()->breadcrumb($breadcrumb); + } + + /** + * All possible parameters + * {GALLERY_THUMB=w=200&h=200&thumburl&thumbsrc&imageurl&orig} + * w and h - optional width and height of the thumbnail + * thumburl - return only the URL of the destination image (large one) + * thumbsrc - url to the thumb, as it's written in the src attribute of the image + * imageurl - full path to the destination image (no proxy) + * actualPreview - large preview will use the original path to the image (no proxy) + */ + function sc_gallery_thumb($parm = '') + { + e107_require_once(e_PLUGIN . 'gallery/includes/gallery_load.php'); + // Load prettyPhoto settings and files. + gallery_load_prettyphoto(); + + $plugPrefs = e107::getPlugConfig('gallery')->getPref(); + $hook = varset($plugPrefs['pp_hook'], 'data-gal'); + + $tp = e107::getParser(); + $parms = eHelper::scParams($parm); + + $w = vartrue($parms['w']) ? $parms['w'] : $tp->thumbWidth(); // 190; // 160; + $h = vartrue($parms['h']) ? $parms['h'] : $tp->thumbHeight(); // 130; + + $class = ($this->slideMode == true) ? 'gallery-slideshow-thumb img-responsive img-fluid img-rounded rounded' : varset($parms['class'], 'gallery-thumb img-responsive img-fluid'); + $rel = ($this->slideMode == true) ? 'prettyPhoto[pp_gal]' : 'prettyPhoto[pp_gal]'; + + //$att = array('aw'=>$w, 'ah'=>$h, 'x'=>1, 'crop'=>1); + $caption = $tp->toAttribute($this->var['media_caption']); + $att = array('w' => $w, 'h' => $h, 'class' => $class, 'alt' => $caption, 'x' => 1, 'crop' => 1); + + + $srcFull = $tp->thumbUrl($this->var['media_url'], $this->attFull); + + if(vartrue($parms['actualPreview'])) + { + $srcFull = $tp->replaceConstants($this->var['media_url'], 'full'); + } + + if(isset($parms['thumburl'])) + { + return $srcFull; + } + elseif(isset($parms['thumbsrc'])) + { + return $tp->thumbUrl($this->var['media_url'], $att); + } + elseif(isset($parms['imageurl'])) + { + return $tp->replaceConstants($this->var['media_url'], 'full'); + } + + $description = $tp->toAttribute($this->var['media_description']); + + $text = ""; + $text .= $tp->toImage($this->var['media_url'], $att); + $text .= ""; + + return $text; + } + + function sc_gallery_cat_title($parm = '') + { + $tp = e107::getParser(); + $url = e107::getUrl()->create('gallery/index/list', $this->var); + if($parm == 'title') + { + return $tp->toHTML($this->var['media_cat_title'], false, 'TITLE'); + } + $text = ""; + $text .= $tp->toHTML($this->var['media_cat_title'], false, 'TITLE'); + $text .= ""; + return $text; + } + + function sc_gallery_cat_url($parm = '') + { + return e107::getUrl()->create('gallery/index/list', $this->var); + } + + function sc_gallery_cat_description($parm = '') + { + $tp = e107::getParser(); + return $tp->toHTML($this->var['media_cat_diz'], true, 'BODY'); + } + + function sc_gallery_baseurl() + { + return e107::getUrl()->create('gallery'); + } + + function sc_gallery_cat_thumb($parm = '') + { + $parms = eHelper::scParams($parm); + + $w = vartrue($parms['w']) ? $parms['w'] : 300; // 260; + $h = vartrue($parms['h']) ? $parms['h'] : 200; // 180; + $att = 'aw=' . $w . '&ah=' . $h . '&x=1'; // 'aw=190&ah=150'; + + $url = e107::getUrl()->create('gallery/index/list', $this->var); + + if(isset($parms['thumbsrc'])) + { + return e107::getParser()->thumbUrl($this->var['media_cat_image'], $att); + } + + $text = ""; + $text .= ""; + $text .= ""; + return $text; + } + + function sc_gallery_nextprev($parm = '') + { + // we passs both fields, the router will convert one of them to 'cat' variable, based on the current URL config + $url = 'route::gallery/index/list?media_cat_category=' . $this->curCat . '--AMP--media_cat_sef=' . $this->var['media_cat_sef'] . '--AMP--frm=--FROM--::full=1'; + $parm = 'total=' . $this->total . '&amount=' . $this->amount . '¤t=' . $this->from . '&url=' . rawurlencode($url); // .'&url='.$url; + $text = e107::getParser()->parseTemplate("{NEXTPREV=" . $parm . "}"); + return $text; + } + + function sc_gallery_slideshow($parm = '') + { + $this->sliderCat = ($parm) ? $parm : vartrue(e107::getPlugPref('gallery', 'slideshow_category'), 1); + + $tmpl = e107::getTemplate('gallery', 'gallery'); + $template = array_change_key_case($tmpl); + + return e107::getParser()->parseTemplate($template['slideshow_wrapper']); + } + + /** + * Display a Grid of thumbnails - useful for home pages. + * Amount per row differs according to device, so they are not set here, only the amount. + * @example {GALLERY_PORTFOLIO: placeholder=1&category=2} + */ + function sc_gallery_portfolio($parm=null) + { + $ns = e107::getRender(); + $tp = e107::getParser(); + // $parm = eHelper::scParams($parms); + $cat = (!empty($parm['category'])) ? $parm['category'] : vartrue(e107::getPlugPref('gallery', 'slideshow_category'), false); //TODO Separate pref? + + $tmpl = e107::getTemplate('gallery', 'gallery'); + $limit = vartrue($parm['limit'], 6); + + $plugPrefs = e107::getPlugConfig('gallery')->getPref(); + $orderBy = varset($plugPrefs['orderby'], 'media_id DESC'); + + $imageQry = (empty($cat) || $cat==1) ? "gallery_image|gallery_image_1|gallery_1" : 'gallery_' . $cat . '|gallery_image_' . $cat; + + + + $list = e107::getMedia()->getImages($imageQry, 0, $limit, null, $orderBy); + + if(count($list) < 1 && vartrue($parm['placeholder'])) + { + $list = array(); + + for($i = 0; $i < $limit; $i++) + { + $list[] = array('media_url' => ''); + } + } + + $template = e107::getTemplate('gallery', 'gallery', 'portfolio'); + + if(!empty($template['start'])) + { + $text = $tp->parseTemplate($template['start'],true, $this); + } + else + { + $text = ''; + } + + //NOTE: Using tablerender() allows the theme developer to set the number of columns etc using col-xx-xx + + foreach($list as $val) + { + $this->var = $val; + + if(empty($template['item'])) + { + $text .= $ns->tablerender('', $this->sc_gallery_thumb('class=gallery_thumb img-responsive img-fluid img-home-portfolio'), 'gallery_portfolio', true); + } + else + { + $text .= $tp->parseTemplate($template['item'],true,$this); + } + + } + + if(!empty($template['end'])) + { + $text .= $tp->parseTemplate($template['end'],true, $this); + } + + return $text; + + } + + + /** + * All possible parameters + * {GALLERY_SLIDES=4|limit=16&template=MY_SLIDESHOW_SLIDE_ITEM} + * first parameter is always number of slides, default is 3 + * limit - (optional) total limit of pcitures to be shown + * template - (optional) template - name of template to be used for parsing the slideshow item + */ + function sc_gallery_slides($parm) + { + $plugPrefs = e107::getPlugConfig('gallery')->getPref(); + $orderBy = varset($plugPrefs['orderby'], 'media_id DESC'); + + $tp = e107::getParser(); + $this->slideMode = true; + $parms = eHelper::scDualParams($parm); + $amount = $parms[1] ? intval($parms[1]) : 3; // vartrue(e107::getPlugPref('gallery','slideshow_perslide'),3); + $parms = $parms[2]; + $limit = (integer) vartrue($parms['limit'], 16); + $list = e107::getMedia()->getImages('gallery_image|gallery_' . $this->sliderCat . '|gallery_image_' . $this->sliderCat, 0, $limit, null, $orderBy); + $tmpl = e107::getTemplate('gallery', 'gallery'); + $tmpl = array_change_key_case($tmpl); // change template key to lowercase (BC fix) + $tmpl_key = vartrue($parms['template'], 'slideshow_slide_item'); + $item_template = $tmpl[$tmpl_key]; // e107::getTemplate('gallery','gallery', vartrue($parms['template'], 'SLIDESHOW_SLIDE_ITEM')); + $catList = e107::getMedia()->getCategories('gallery'); + $cat = $catList['gallery_' . $this->sliderCat]; + + $count = 1; + $inner = ''; + foreach($list as $row) + { + $this->setVars($row) + ->addVars($cat); + + $inner .= ($count == 1) ? "\n\n\n\n\n" : ""; + + if($count == $amount) + { + $count = 1; + $this->slideCount++; + } + else + { + $count++; + } + } + + $inner .= ($count != 1) ? "" : ""; + return $inner; + } + + + function sc_gallery_jumper($parm) + { + // echo "SlideCount=".$this->slideCount; + if($this->slideCount == 1 && deftrue('E107_DBG_BASIC')) + { + return "gallery-jumper must be loaded after Gallery-Slides"; + } + + $text = ''; + for($i = 1; $i < ($this->slideCount); $i++) + { + $val = ($parm == 'space') ? " " : $i; + $text .= '' . $val . ''; + } + + return $text; + + } +} diff --git a/e107_plugins/gallery/gallery.php b/e107_plugins/gallery/gallery.php index 08e282e66..ac7a732e9 100644 --- a/e107_plugins/gallery/gallery.php +++ b/e107_plugins/gallery/gallery.php @@ -1,169 +1,169 @@ -catList = e107::getMedia()->getCategories('gallery'); - - if((vartrue($_GET['cat'])) && isset($this->catList[$_GET['cat']])) - { - $this->showImages($_GET['cat']); - } - else - { - $this->listCategories(); - } - } - - - /** - * Convert legacy template from ['list_start'] etc. to ['list']['start'] - * @return array|string - */ - private function getTemplate() - { - $template = e107::getTemplate('gallery'); - - $oldKeys = array( - 'list_start', 'list_item', 'list_caption', 'list_end', - 'cat_start', 'cat_item', 'cat_caption', 'cat_end' - ); - - if(isset($template['list_start'])) - { - foreach($oldKeys as $k) - { - list($main,$sub) = explode("_",$k); - $template[$main][$sub] = $template[$k]; - unset($template[$k]); - - } - - - } - - return $template; - } - - function listCategories() - { - - - $template = $this->getTemplate(); - $template = array_change_key_case($template); - $sc = e107::getScBatch('gallery', true); - - if(defset('BOOTSTRAP') === true || defset('BOOTSTRAP') === 2) // Convert bootstrap3 to bootstrap2 compat. - { - $template['cat_start'] = str_replace('row', 'row-fluid', $template['cat_start']); - } - - $text = e107::getParser()->parseTemplate($template['cat']['start'], true, $sc); - - foreach($this->catList as $val) - { - $sc->setVars($val); - $text .= e107::getParser()->parseTemplate($template['cat']['item'], true, $sc); - } - - $text .= e107::getParser()->parseTemplate($template['cat']['end'], true, $sc); - - $caption = e107::getParser()->parseTemplate($template['cat']['caption'], true, $sc); - - e107::getRender()->tablerender($caption, $text); - } - - - function showImages($cat) - { - $plugPrefs = e107::getPlugConfig('gallery')->getPref(); - $mes = e107::getMessage(); - $tp = e107::getParser(); - $template = $this->getTemplate(); - $template = array_change_key_case($template); - $sc = e107::getScBatch('gallery', true); - - if(defset('BOOTSTRAP') === true || defset('BOOTSTRAP') === 2) // Convert bootsrap3 to bootstrap2 compat. - { - $template['list_start'] = str_replace('row', 'row-fluid', $template['list_start']); - } - - $sc->total = e107::getMedia()->countImages($cat); - $sc->amount = varset($plugPrefs['perpage'], 12); - $sc->curCat = $cat; - $sc->from = ($_GET['frm']) ? intval($_GET['frm']) : 0; - $orderBy = varset($plugPrefs['orderby'], 'media_id DESC'); - - $list = e107::getMedia()->getImages($cat, $sc->from, $sc->amount, null, $orderBy); - $catname = $tp->toHTML($this->catList[$cat]['media_cat_title'], false, 'defs'); - - $inner = ""; - - foreach($list as $row) - { - $sc->setVars($row); - $inner .= $tp->parseTemplate($template['list']['item'], true, $sc); - } - - $text = $tp->parseTemplate($template['list']['start'], true, $sc); - $text .= $inner; - $text .= $tp->parseTemplate($template['list']['end'], true, $sc); - - $caption = $tp->parseTemplate($template['list']['caption'], true, $sc); - - e107::getRender()->tablerender($caption, $mes->render() . $text); - - } - -} - - -new gallery; - -require_once(FOOTERF); -exit; +catList = e107::getMedia()->getCategories('gallery'); + + if((vartrue($_GET['cat'])) && isset($this->catList[$_GET['cat']])) + { + $this->showImages($_GET['cat']); + } + else + { + $this->listCategories(); + } + } + + + /** + * Convert legacy template from ['list_start'] etc. to ['list']['start'] + * @return array|string + */ + private function getTemplate() + { + $template = e107::getTemplate('gallery'); + + $oldKeys = array( + 'list_start', 'list_item', 'list_caption', 'list_end', + 'cat_start', 'cat_item', 'cat_caption', 'cat_end' + ); + + if(isset($template['list_start'])) + { + foreach($oldKeys as $k) + { + list($main,$sub) = explode("_",$k); + $template[$main][$sub] = $template[$k]; + unset($template[$k]); + + } + + + } + + return $template; + } + + function listCategories() + { + + + $template = $this->getTemplate(); + $template = array_change_key_case($template); + $sc = e107::getScBatch('gallery', true); + + if(defset('BOOTSTRAP') === true || defset('BOOTSTRAP') === 2) // Convert bootstrap3 to bootstrap2 compat. + { + $template['cat_start'] = str_replace('row', 'row-fluid', $template['cat_start']); + } + + $text = e107::getParser()->parseTemplate($template['cat']['start'], true, $sc); + + foreach($this->catList as $val) + { + $sc->setVars($val); + $text .= e107::getParser()->parseTemplate($template['cat']['item'], true, $sc); + } + + $text .= e107::getParser()->parseTemplate($template['cat']['end'], true, $sc); + + $caption = e107::getParser()->parseTemplate($template['cat']['caption'], true, $sc); + + e107::getRender()->tablerender($caption, $text); + } + + + function showImages($cat) + { + $plugPrefs = e107::getPlugConfig('gallery')->getPref(); + $mes = e107::getMessage(); + $tp = e107::getParser(); + $template = $this->getTemplate(); + $template = array_change_key_case($template); + $sc = e107::getScBatch('gallery', true); + + if(defset('BOOTSTRAP') === true || defset('BOOTSTRAP') === 2) // Convert bootsrap3 to bootstrap2 compat. + { + $template['list_start'] = str_replace('row', 'row-fluid', $template['list_start']); + } + + $sc->total = e107::getMedia()->countImages($cat); + $sc->amount = varset($plugPrefs['perpage'], 12); + $sc->curCat = $cat; + $sc->from = ($_GET['frm']) ? intval($_GET['frm']) : 0; + $orderBy = varset($plugPrefs['orderby'], 'media_id DESC'); + + $list = e107::getMedia()->getImages($cat, $sc->from, $sc->amount, null, $orderBy); + $catname = $tp->toHTML($this->catList[$cat]['media_cat_title'], false, 'defs'); + + $inner = ""; + + foreach($list as $row) + { + $sc->setVars($row); + $inner .= $tp->parseTemplate($template['list']['item'], true, $sc); + } + + $text = $tp->parseTemplate($template['list']['start'], true, $sc); + $text .= $inner; + $text .= $tp->parseTemplate($template['list']['end'], true, $sc); + + $caption = $tp->parseTemplate($template['list']['caption'], true, $sc); + + e107::getRender()->tablerender($caption, $mes->render() . $text); + + } + +} + + +new gallery; + +require_once(FOOTERF); +exit; diff --git a/e107_plugins/gallery/languages/English/English_global.php b/e107_plugins/gallery/languages/English/English_global.php index 3506818a2..c77a39f3b 100644 --- a/e107_plugins/gallery/languages/English/English_global.php +++ b/e107_plugins/gallery/languages/English/English_global.php @@ -1,14 +1,14 @@ - varset($gp['slideshow_effect'], 'scrollHorz'), - 'speed' => varset($gp['slideshow_duration'], 1000), - 'timeout' => varset($gp['slideshow_freq'], 4000), -); - -e107::js('settings', array('gallery' => $settings)); - -$text = e107::getParser()->parseTemplate("{GALLERY_SLIDESHOW}"); -e107::getRender()->tablerender(LAN_PLUGIN_GALLERY_TITLE, $text, 'gallery_slideshow'); -unset($text); -unset($gp); + varset($gp['slideshow_effect'], 'scrollHorz'), + 'speed' => varset($gp['slideshow_duration'], 1000), + 'timeout' => varset($gp['slideshow_freq'], 4000), +); + +e107::js('settings', array('gallery' => $settings)); + +$text = e107::getParser()->parseTemplate("{GALLERY_SLIDESHOW}"); +e107::getRender()->tablerender(LAN_PLUGIN_GALLERY_TITLE, $text, 'gallery_slideshow'); +unset($text); +unset($gp); diff --git a/e107_plugins/gallery/templates/gallery_template.php b/e107_plugins/gallery/templates/gallery_template.php index 3e8cf44f5..c9e1159ed 100644 --- a/e107_plugins/gallery/templates/gallery_template.php +++ b/e107_plugins/gallery/templates/gallery_template.php @@ -1,195 +1,195 @@ - -'; - -$GALLERY_TEMPLATE['list']['item'] = ' -
-
- {GALLERY_THUMB=w=300&h=200} -
{GALLERY_CAPTION}
-
-
-'; - -$GALLERY_TEMPLATE['list']['end'] = ' - -
- - -
-'; - -// Bootstrap3 Compatible. -$GALLERY_TEMPLATE['cat']['caption'] = LAN_PLUGIN_GALLERY_TITLE; - -$GALLERY_TEMPLATE['cat']['start'] = '{GALLERY_BREADCRUMB} - -'; - -// {GALLERY_SLIDESHOW=X} X = Gallery Category. Default: 1 (ie. 'gallery_1') Overrides preference in admin. -// {GALLERY_SLIDES=X} X = number of items per slide. -// {GALLERY_JUMPER=space} will remove numbers and just leave spaces. - -$GALLERY_TEMPLATE['slideshow_wrapper'] = ' - - - -'; - -$GALLERY_TEMPLATE['slideshow_slide_item'] = '{GALLERY_THUMB: w=150&h=120}'; - -$GALLERY_TEMPLATE['prettyphoto']['content'] = ' -
-
 
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-'; - -$GALLERY_TEMPLATE['prettyphoto']['gallery_item'] = ' - -'; - -$GALLERY_TEMPLATE['prettyphoto']['image_item'] = ' - -'; - -$GALLERY_TEMPLATE['prettyphoto']['flash_item'] = ' - - - - - - - -'; - -$GALLERY_TEMPLATE['prettyphoto']['quicktime_item'] = ' - - - - - - -'; - -$GALLERY_TEMPLATE['prettyphoto']['iframe_item'] = ' - -'; - -$GALLERY_TEMPLATE['prettyphoto']['inline_item'] = ' -
{content}
-'; - -$GALLERY_TEMPLATE['prettyphoto']['custom_item'] = ''; - -$GALLERY_TEMPLATE['prettyphoto']['social_item'] = ' -
- - -
-'; - - - - - - -/* - -$GALLERY_TEMPLATE['portfolio']['start'] = '<-- start portfolio -->'; -$GALLERY_TEMPLATE['portfolio']['item'] = '{GALLERY_CAPTION=text}'; -$GALLERY_TEMPLATE['portfolio']['end'] = '<-- end portfolio -->'; - -*/ + +'; + +$GALLERY_TEMPLATE['list']['item'] = ' +
+
+ {GALLERY_THUMB=w=300&h=200} +
{GALLERY_CAPTION}
+
+
+'; + +$GALLERY_TEMPLATE['list']['end'] = ' + +
+ + +
+'; + +// Bootstrap3 Compatible. +$GALLERY_TEMPLATE['cat']['caption'] = LAN_PLUGIN_GALLERY_TITLE; + +$GALLERY_TEMPLATE['cat']['start'] = '{GALLERY_BREADCRUMB} + +'; + +// {GALLERY_SLIDESHOW=X} X = Gallery Category. Default: 1 (ie. 'gallery_1') Overrides preference in admin. +// {GALLERY_SLIDES=X} X = number of items per slide. +// {GALLERY_JUMPER=space} will remove numbers and just leave spaces. + +$GALLERY_TEMPLATE['slideshow_wrapper'] = ' + + + +'; + +$GALLERY_TEMPLATE['slideshow_slide_item'] = '{GALLERY_THUMB: w=150&h=120}'; + +$GALLERY_TEMPLATE['prettyphoto']['content'] = ' +
+
 
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+'; + +$GALLERY_TEMPLATE['prettyphoto']['gallery_item'] = ' + +'; + +$GALLERY_TEMPLATE['prettyphoto']['image_item'] = ' + +'; + +$GALLERY_TEMPLATE['prettyphoto']['flash_item'] = ' + + + + + + + +'; + +$GALLERY_TEMPLATE['prettyphoto']['quicktime_item'] = ' + + + + + + +'; + +$GALLERY_TEMPLATE['prettyphoto']['iframe_item'] = ' + +'; + +$GALLERY_TEMPLATE['prettyphoto']['inline_item'] = ' +
{content}
+'; + +$GALLERY_TEMPLATE['prettyphoto']['custom_item'] = ''; + +$GALLERY_TEMPLATE['prettyphoto']['social_item'] = ' +
+ + +
+'; + + + + + + +/* + +$GALLERY_TEMPLATE['portfolio']['start'] = '<-- start portfolio -->'; +$GALLERY_TEMPLATE['portfolio']['item'] = '{GALLERY_CAPTION=text}'; +$GALLERY_TEMPLATE['portfolio']['end'] = '<-- end portfolio -->'; + +*/ diff --git a/e107_plugins/gallery/url/rewrite_url.php b/e107_plugins/gallery/url/rewrite_url.php index 1899cef6d..4d65a4f4a 100644 --- a/e107_plugins/gallery/url/rewrite_url.php +++ b/e107_plugins/gallery/url/rewrite_url.php @@ -1,60 +1,60 @@ - array( - 'allowMain' => true, - 'format' => 'path', - 'defaultRoute' => 'index/category', - - // false - disable all parameters passed to assemble method by default - 'allowVars' => array('cat', 'frm'), - - // custom assemble/parse URL regex template - 'varTemplates' => array('galleryCat' => '[\w\pL\s\-+.,]+'), - ), - - // rule set array - 'rules' => array( - '/' => 'index/category', - // allow only mapped vars - cat and frm parameters to be passed - '' => array('index/list', 'mapVars' => array('media_cat_sef' => 'cat', 'from' => 'frm')), - ) - ); - } - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - XXX LANS - static $admin = array( - 'labels' => array( - 'name' => LAN_PLUGIN_GALLERY_TITLE, // Module name - 'label' => LAN_PLUGIN_GALLERY_SEF_01, // Current profile name - 'description' => LAN_PLUGIN_GALLERY_SEF_02, - 'examples' => array('{SITEURL}gallery/my-gallery-title'), // - ), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } -} + array( + 'allowMain' => true, + 'format' => 'path', + 'defaultRoute' => 'index/category', + + // false - disable all parameters passed to assemble method by default + 'allowVars' => array('cat', 'frm'), + + // custom assemble/parse URL regex template + 'varTemplates' => array('galleryCat' => '[\w\pL\s\-+.,]+'), + ), + + // rule set array + 'rules' => array( + '/' => 'index/category', + // allow only mapped vars - cat and frm parameters to be passed + '' => array('index/list', 'mapVars' => array('media_cat_sef' => 'cat', 'from' => 'frm')), + ) + ); + } + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance - XXX LANS + static $admin = array( + 'labels' => array( + 'name' => LAN_PLUGIN_GALLERY_TITLE, // Module name + 'label' => LAN_PLUGIN_GALLERY_SEF_01, // Current profile name + 'description' => LAN_PLUGIN_GALLERY_SEF_02, + 'examples' => array('{SITEURL}gallery/my-gallery-title'), // + ), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } +} diff --git a/e107_plugins/gallery/url/url.php b/e107_plugins/gallery/url/url.php index 0704cb1f4..2711445c1 100644 --- a/e107_plugins/gallery/url/url.php +++ b/e107_plugins/gallery/url/url.php @@ -1,56 +1,56 @@ - array( - 'allowMain' => true, - 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored - 'defaultRoute' => 'index/category', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ - - // false - disable all parameters passed to assemble method by default - 'allowVars' => array('cat', 'frm'), - ), - - // rule set array - 'rules' => array( - '/' => 'index/category', - 'list' => array('index/list', 'mapVars' => array('media_cat_sef' => 'cat', 'from' => 'frm'), 'allowVars' => array('cat', 'frm'),), - ) - ); - } - - /** - * Admin callback - * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) - */ - public function admin() - { - // static may be used for performance - XXX LANS - static $admin = array( - 'labels' => array( - 'name' => LAN_PLUGIN_GALLERY_TITLE, // Module name - 'label' => LAN_PLUGIN_GALLERY_SEF_04, // Current profile name - 'description' => LAN_PLUGIN_GALLERY_SEF_03, - 'examples' => array("{e_PLUGIN_ABS}gallery/?cat=gallery_1") - ), - 'form' => array(), // Under construction - additional configuration options - 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity - ); - - return $admin; - } -} + array( + 'allowMain' => true, + 'format' => 'path', // get|path - notify core for the current URL format, if set to 'get' rules will be ignored + 'defaultRoute' => 'index/category', // [optional] default empty; route (no leading module) used when module is found with no additional controller/action information e.g. /news/ + + // false - disable all parameters passed to assemble method by default + 'allowVars' => array('cat', 'frm'), + ), + + // rule set array + 'rules' => array( + '/' => 'index/category', + 'list' => array('index/list', 'mapVars' => array('media_cat_sef' => 'cat', 'from' => 'frm'), 'allowVars' => array('cat', 'frm'),), + ) + ); + } + + /** + * Admin callback + * Language file not loaded as all language data is inside the lan_eurl.php (loaded by default on administration URL page) + */ + public function admin() + { + // static may be used for performance - XXX LANS + static $admin = array( + 'labels' => array( + 'name' => LAN_PLUGIN_GALLERY_TITLE, // Module name + 'label' => LAN_PLUGIN_GALLERY_SEF_04, // Current profile name + 'description' => LAN_PLUGIN_GALLERY_SEF_03, + 'examples' => array("{e_PLUGIN_ABS}gallery/?cat=gallery_1") + ), + 'form' => array(), // Under construction - additional configuration options + 'callbacks' => array(), // Under construction - could be used for e.g. URL generator functionallity + ); + + return $admin; + } +} diff --git a/e107_plugins/gsitemap/gsitemap_sql.php b/e107_plugins/gsitemap/gsitemap_sql.php index 9a3649bed..a3308e8be 100644 --- a/e107_plugins/gsitemap/gsitemap_sql.php +++ b/e107_plugins/gsitemap/gsitemap_sql.php @@ -1,13 +1,13 @@ -CREATE TABLE gsitemap ( - gsitemap_id int(11) unsigned NOT NULL auto_increment, - gsitemap_name varchar(200) NOT NULL default '', - gsitemap_url varchar(200) NOT NULL default '', - gsitemap_lastmod varchar(15) NOT NULL default '', - gsitemap_freq varchar(10) NOT NULL default '', - gsitemap_priority char(3) NOT NULL default '', - gsitemap_cat varchar(100) NOT NULL default '', - gsitemap_order int(3) NOT NULL default '0', - gsitemap_img varchar(50) NOT NULL default '', - gsitemap_active int(3) NOT NULL default '0', - PRIMARY KEY (gsitemap_id) +CREATE TABLE gsitemap ( + gsitemap_id int(11) unsigned NOT NULL auto_increment, + gsitemap_name varchar(200) NOT NULL default '', + gsitemap_url varchar(200) NOT NULL default '', + gsitemap_lastmod varchar(15) NOT NULL default '', + gsitemap_freq varchar(10) NOT NULL default '', + gsitemap_priority char(3) NOT NULL default '', + gsitemap_cat varchar(100) NOT NULL default '', + gsitemap_order int(3) NOT NULL default '0', + gsitemap_img varchar(50) NOT NULL default '', + gsitemap_active int(3) NOT NULL default '0', + PRIMARY KEY (gsitemap_id) ) ENGINE=MyISAM; \ No newline at end of file diff --git a/e107_plugins/import/admin_import.php b/e107_plugins/import/admin_import.php index 8ab17cc9e..86124ca05 100644 --- a/e107_plugins/import/admin_import.php +++ b/e107_plugins/import/admin_import.php @@ -1,1689 +1,1689 @@ - array( - 'controller' => 'import_main_ui', - 'path' => null, - 'ui' => 'import_admin_form_ui', - 'uipath' => null - ), - 'cat' => array( - 'controller' => 'import_cat_ui', - 'path' => null, - 'ui' => 'import_cat_form_ui', - 'uipath' => null - ) - ); - - protected $adminMenu = array( - 'main/list' => array('caption'=> LAN_LIST, 'perm' => '0'), - // 'main/create' => array('caption'=> 'Create import', 'perm' => '0'), -// 'cat/list' => array('caption'=> 'Categories', 'perm' => '0'), -// 'cat/create' => array('caption'=> "Create Category", 'perm' => '0'), - // 'main/prefs' => array('caption'=> LAN_PREFS, 'perm' => '0'), - // 'main/custom' => array('caption'=> 'Custom Page', 'perm' => '0') - ); - - protected $adminMenuAliases = array( - 'main/edit' => 'main/list' - ); - - protected $menuTitle = LAN_PLUGIN_IMPORT_NAME; -} - - -class import_main_ui extends e_admin_ui -{ - - protected $pluginTitle = LAN_PLUGIN_IMPORT_NAME; - protected $pluginName = 'import'; - protected $table = false; - - protected $providers = array(); // the different types of import. - protected $deleteExisting = false; // delete content from existing table during import. - protected $selectedTables = array(); // User selection of what tables to import. eg. news, pages etc. - protected $importClass = null; - protected $checked_class_list = ''; - - // Definitions of available areas to import - protected $importTables = array( - 'users' => array('message' => LAN_CONVERT_25, 'classfile' => 'import_user_class.php', 'classname' => 'user_import'), - 'userclass' => array('message' => LAN_CONVERT_73, 'nolist'=>true, 'classfile' => 'import_user_class.php', 'classname' => 'userclass_import'), - - 'news' => array('message' => LAN_CONVERT_28, 'classfile' => 'import_news_class.php', 'classname' => 'news_import'), - 'newscategory' => array('message' => LAN_CONVERT_74, 'nolist'=>true, 'classfile' => 'import_news_class.php', 'classname' => 'newscategory_import'), - - 'page' => array('message' => LAN_CONVERT_65, 'classfile' => 'import_page_class.php', 'classname' => 'page_import'), - 'pagechapter' => array('message' => LAN_CONVERT_66, 'nolist'=>true, 'classfile' => 'import_page_class.php', 'classname' => 'pagechapter_import'), - 'links' => array('message' => LAN_CONVERT_67, 'classfile' => 'import_links_class.php', 'classname' => 'links_import'), - 'media' => array('message' => LAN_CONVERT_68, 'classfile' => 'import_media_class.php', 'classname' => 'media_import'), - 'forum' => array('message' => LAN_CONVERT_69, 'classfile' => 'import_forum_class.php', 'classname' => 'forum_import'), - 'forumthread' => array('message' => LAN_CONVERT_70, 'classfile' => 'import_forum_class.php', 'classname' => 'forumthread_import', 'nolist'=>true), - 'forumpost' => array('message' => LAN_CONVERT_71, 'classfile' => 'import_forum_class.php', 'classname' => 'forumpost_import', 'nolist'=>true), - 'forumtrack' => array('message' => LAN_CONVERT_72, 'classfile' => 'import_forum_class.php', 'classname' => 'forumtrack_import', 'nolist'=>true), - // 'comments' => array('message'=> LAN_COMMENTS), - - // 'polls' => array('message' => LAN_CONVERT_27) - ); - - // without any Order or Limit. - - - - function init() - { - $fl = e107::getFile(); - - $importClassList = $fl->get_files(e_PLUGIN.'import/providers', "^.+?_import_class\.php$", "standard", 1); - - foreach($importClassList as $file) - { - - - $tag = str_replace('_class.php','',$file['fname']); - - $key = str_replace("_import_class.php","",$file['fname']); - - if($key === 'template') - { - continue; - } - - include_once($file['path'].$file['fname']); // This will set up the variables - - $this->providers[$key] = $this->getMeta($tag); - - if(!empty($_GET['type'])) - { - $this->importClass = filter_var($_GET['type'])."_import"; - } - - } - - - uksort($this->providers,'strcasecmp'); - - - } - - - function help() - { - - return "Some help text for admin-ui"; - - } - - - - - - function getMeta($class_name) - { - if(class_exists($class_name)) - { - $obj = new $class_name; - return array('title' => vartrue($obj->title), 'description' => vartrue($obj->description), 'supported' => vartrue($obj->supported)); - } - else - { - e107::getMessage()->addDebug("Missing class: ".$class_name); - } - - } - - - - - - // After selection - decide where to route things. - function importPage() - { - - // print_a($_POST); - - if(!empty($_POST['import_delete_existing_data'])) - { - $this->deleteExisting = varset($_POST['import_delete_existing_data'],0); - } - - if(!empty($_POST['classes_select'])) - { - $this->checked_class_list = implode(',',$_POST['classes_select']); - } - - if(!empty($_POST['createUserExtended'])) //TODO - { - $this->createUserExtended = true; - } - - if(!empty($_POST['selectedTables'])) - { - $this->selectedTables = $_POST['selectedTables']; - } - - if(!empty($_POST['runConversion'])) // default method. - { - $this->runConversion($_POST['import_source']); - return; - } - - - - - $this->showImportOptions($_GET['type']); - - } - - - - - - - - - - function listPage() - { - $mes = e107::getMessage(); - $frm = e107::getForm(); - - $tableCount = 0; - // $mes->addDebug(print_a($this->providers,true)); - - $text = " -
-
- ".'DBLAN_10'." - ".$frm->hidden('mode','main')." - ".$frm->hidden('action','import')." - - - "; - - foreach($this->importTables as $key=>$val) - { - if(!empty($val['nolist'])){ continue; } - $text .= "\n"; - } - - - $text .= " - - - - - - "; - foreach($this->importTables as $val) // 1 column for each of users, news, forum etc. - { - if(vartrue($val['nolist'])){ continue; } - $text .= ""; - $tableCount++; - } - - $text.=" - - - - - "; - /* - $text .= " - - - - "; - - for ($i=0; $i < $tableCount-1; $i++) - { - $text .= ""; - } - - - $text .= ""; - */ - - foreach ($this->providers as $k=>$info) - { - $title = $info['title']; - - $iconFile = e_PLUGIN."import/images/".str_replace("_import","",strtolower($k)).".png"; - - $icon = (file_exists($iconFile)) ? "" : ""; - - $text .= " - \n"; - - foreach($this->importTables as $key=>$val) - { - if(vartrue($val['nolist'])){ continue; } - $text .= "\n"; - } - - $text .= " - - "; - } - - - $text .= " - -
".LAN_CONVERT_06."".$val['message']."".LAN_OPTIONS."
CSV".ADMIN_TRUE_ICON." ".$frm->admin_button('import_type', 'csv', 'other',"Select")."
".$icon.$title."
".$info['description']."
".(in_array($key,$info['supported']) ? ADMIN_TRUE_ICON : " ").""; - - $text .= $frm->admin_button('type', $k, 'other',LAN_CONVERT_64); - // $text .= $frm->admin_button('import_type', $k, 'other',"Select"); - - $text .= " -
-
- ".$frm->hidden('trigger_import',1)." - -
-
-
"; - - echo $mes->render().$text; - // $ns->tablerender(LAN_PLUGIN_IMPORT_NAME, $mes->render().$text); - - } - - - - - - function runConversion($import_source) - { - $frm = e107::getForm(); - $ns = e107::getRender(); - $mes = e107::getMessage(); - - $abandon = TRUE; - - switch ($import_source) - { - case 'csv' : - - break; - - case 'db' : - if($this->dbImport() == false) - { - $abandon = true; - } - break; - - case 'rss' : - if($this->rssImport() == false) - { - $abandon = true; - } - break; - } - - -// if ($msg) -// { -// $mes->add($msg, E_MESSAGE_INFO); // $ns -> tablerender(LAN_CONVERT_30, $msg); -// $msg = ''; -// } - - if ($abandon) - { - // unset($_POST['do_conversion']); - $text = " -
-
- ".$frm->admin_button('dummy_continue',LAN_CONTINUE, 'execute')." -
-
"; - echo $mes->render(). $text; - - // $ns -> tablerender(LAN_CONVERT_30,$mes->render(). $text); - - } - } - - - - - function renderConfig() - { - - } - - - - - - - - - function showImportOptions($type='csv') - { - global $csv_names, $e_userclass; - $mode = $this->importClass; - - $frm = e107::getForm(); - $ns = e107::getRender(); - - $mes = e107::getMessage(); - - if (class_exists($mode)) - { - $mes->addDebug("Class Available: ".$mode); - $proObj = new $mode; - if($proObj->init()===FALSE) - { - return; - } - } - - $message = "".LAN_CONVERT_05.""; - $mes->add($message, E_MESSAGE_WARNING); - - $text = " -
- - - - - "; - - - - /* - if($mode == "csv") - { - $text .= " - - - - - - - - - - - - - - "; - - } - else - */ - - $importType = $proObj->title; - - if($proObj->sourceType == 'db' || !$proObj->sourceType) // STANDARD db Setup - { - $databases = $this->getDatabases(); - $prefix = (varset($_POST['dbParamPrefix']) ? $_POST['dbParamPrefix'] : $proObj->mprefix); - /* - $text .= " - - - - - - - - - - - - - ";*/ - - $text .= " - - - - - - - - "; - - } - - - if(method_exists($proObj,"config")) // Config Found in Class - render options from it. - { - if($ops = $proObj->config()) - { - foreach($ops as $key=>$val) - { - $text .= " - - - \n"; - } - } - } - - - if($proObj->sourceType) - { - $text .= "\n"; - } - else - { - $text .= ""; - } - - - - - // if($mode != 'csv') - { - $text .= " - - - "; - } - - - $text .= " - - - - "; - - //TODO - /* - if(in_array('users',$proObj->supported)) - { - $text .= " - - - "; - } - */ - - if(varset($proObj->defaultClass) !== false) - { - $text .= " - - "; - } - - $action = varset($proObj->action,'runConversion'); - $text .= "
".LAN_CONVERT_07."\n -
".LAN_CONVERT_36."
".LAN_CONVERT_17." - - - - - ".LAN_CONVERT_18."
$importType ".LAN_CONVERT_19."
$importType ".LAN_CONVERT_20." - -
Must be different from the one e107 uses.
-
$importType ".LAN_CONVERT_21."
$importType ".LAN_CONVERT_22."".$frm->select('dbParamDatabase', $databases, null, array('required'=>1), LAN_SELECT."...")."
$importType ".LAN_CONVERT_23."".$frm->text('dbParamPrefix', $prefix, 100)." - -
".$val['caption']."".$val['html']; - $text .= (vartrue($val['help'])) ? "
".$val['help']."
" : ""; - $text .= "
$importType ".LAN_CONVERT_24.""; - - $defCheck = (count($proObj->supported)==1) ? true : false; - foreach ($this->importTables as $k => $v) - { - if(in_array($k, $proObj->supported)) // display only the options supported. - { - $text .= $frm->checkbox('selectedTables['.$k.']', $k, $defCheck,array('label'=>$v['message'])); - - - //$text .= " ".$v['message']; - // $text .= "
"; - } - } - $text .= "
".LAN_CONVERT_38."".$frm->radio_switch('import_delete_existing_data', $_POST['import_delete_existing_data'])." -
".LAN_CONVERT_39."
Create Extended User Fields".$frm->checkbox('createUserExtended', 1,'', array('label'=>' ','title'=>'Will automatically add missing user-fields when found.'))." -
".LAN_CONVERT_16.""; - $text .= $e_userclass->vetted_tree('classes_select',array($e_userclass,'checkbox'), varset($_POST['classes_select']),'main,admin,classes,matchclass, no-excludes'); - $text .= "
-
".$frm->admin_button($action,LAN_CONTINUE, 'execute'). - - $frm->admin_button('back',LAN_CANCEL, 'cancel')." - - -
-
"; - - // Now a little bit of JS to initialise some of the display divs etc - // $temp = ''; - // if(varset($import_source)) { $temp .= "disp('{$import_source}');"; } - // if (varset($current_db_type)) $temp .= " flagbits('{$current_db_type}');"; - // if (varset($temp)) $text .= ""; - - $this->addTitle($importType); - echo $mes->render().$text; - - // $ns -> tablerender(LAN_PLUGIN_IMPORT_NAME.SEP.$importType, $mes->render().$text); - - } - - - private function getDatabases() - { - $tmp = e107::getDb()->gen("SHOW DATABASES"); - $databases = e107::getDb()->db_getList(); - - $arr = array(); - - $exclude = array('mysql', 'information_schema', 'performance_schema', 'phpmyadmin'); - - foreach($databases as $v) - { - $id = $v['Database']; - - if(in_array($id,$exclude)) - { - continue; - } - - $arr[$id] = $id; - - } - - return $arr; - - - } - - - - function rssImport() - { - global $current_db_type; - - $mes = e107::getMessage(); - $mes->addDebug("Loading: RSS"); - - if(!varset($_POST['runConversion'])) - { - $mes->addWarning("Under Construction"); - } - - return $this->dbImport('xml'); - - } - - - - /** MAIN IMPORT AREA */ - function dbImport($mode='db') - { - - $mes = e107::getMessage(); - $tp = e107::getParser(); - - $mes->addDebug("dbImport(): Loading: ".$this->importClass); - - if(!is_array($this->importTables)) - { - $mes->addError("dbImport(): No areas selected for import"); // db connect failed - return false; - } - - if (class_exists($this->importClass)) - { - $mes->addDebug("dbImport(): Converter Class Available: ".$this->importClass); - $converter = new $this->importClass ; - $converter->init(); - } - else - { - $mes->addError(LAN_CONVERT_42. "[".$this->importClass."]"); - $mes->addDebug("dbImport(): Class NOT Available: ".$this->importClass); - - return false; - } - - - if($mode == 'db') // Don't do DB check on RSS/XML - { - if (empty($_POST['dbParamDatabase'])) - { - $mes->addError(LAN_CONVERT_41); - return false; - } - - $result = $converter->database($tp->filter($_POST['dbParamDatabase']), $tp->filter($_POST['dbParamPrefix'])); - - // $result = $converter->database($tp->filter($_POST['dbParamDatabase']), $tp->filter($_POST['dbParamPrefix']), true); - - if ($result !== true) - { - $mes->addError(LAN_CONVERT_43.": ".$result); // db connect failed - return false; - } - } - - - if(vartrue($converter->override)) - { - $mes->addDebug("dbImport(): Override Active!" ); - return; - } - - - - // Return - foreach($this->selectedTables as $k => $tm) - { - $v = $this->importTables[$k]; - - $loopCounter = 0; - $errorCounter = 0; - - if (is_readable($v['classfile'])) // Load our class for either news, pages etc. - { - $mes->addDebug("dbImport(): Including File: ".$v['classfile']); - require_once($v['classfile']); - } - else - { - $mes->addError(LAN_CONVERT_45.': '.$v['classfile']); // can't read class file. - return false; - } - - $mes->addDebug("dbImport(): Importing: ".$k); - - $exporter = new $v['classname']; // Writes the output data - - if(is_object($exporter)) - { - $mes->addDebug("dbImport(): Exporter Class Initiated: ".$v['classname']); - - if(is_object($exporter->helperClass)) - { - $mes->addDebug("dbImport(): Initiated Helper Class"); - $converter->helperClass = $exporter->helperClass; - } - - } - else - { - $mes->addDebug("dbImport(): Couldn't Initiate Class: ".$v['classname']); - } - - - $result = $converter->setupQuery($k, !$this->deleteExisting); - - if ($result !== true) - { - $mes->addError(LAN_CONVERT_44.' '.$k); // couldn't set query - break; - } - - - - - if($k == 'users') // Do any type-specific default setting - { - $mes->addDebug("dbImport(): Overriding Default for user_class: ".$this->checked_class_list); - $exporter->overrideDefault('user_class', $this->checked_class_list); - // break; - } - - if ($this->deleteExisting == true) - { - $mes->addDebug("dbImport(): Emptying target table. "); - $exporter->emptyTargetDB(); // Clean output DB - reasonably safe now - } - - while ($row = $converter->getNext($exporter->getDefaults(),$mode)) - { - $loopCounter++; - $result = $exporter->saveData($row); - if ($result !== TRUE) - { - $errorCounter++; - $line_error = $exporter->getErrorText($result); - // if ($msg) $msg .= "
"; - $msg = str_replace(array('[x]','[y]'),array($line_error,$k),LAN_CONVERT_46).$loopCounter; - $mes->addError($msg); // couldn't set query - } - } - - $converter->endQuery(); - - unset($exporter); - - - $msg = str_replace(array('[x]','[y]', '[z]','[w]'), - array($loopCounter,$loopCounter-$errorCounter,$errorCounter, $k),LAN_CONVERT_47); - $mes->addSuccess($msg); // couldn't set query - } - - - - - - - - - - - return true; - - // $abandon = FALSE; - } - - - - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - -// Source DB types (i.e. CMS types) supported. Key of each element is the 'short code' for the type -$import_class_names = array(); // Title -$import_class_comment = array(); // Descriptive comment -$import_class_support = array(); // Array of data types supported - -// Definitions of available areas to import -$db_import_blocks = array( - 'users' => array('message' => LAN_CONVERT_25, 'classfile' => 'import_user_class.php', 'classname' => 'user_import'), - 'news' => array('message' => LAN_CONVERT_28, 'classfile' => 'import_news_class.php', 'classname' => 'news_import'), - 'page' => array('message' => "Pages", 'classfile' => 'import_page_class.php', 'classname' => 'page_import'), - 'links' => array('message' => "Links", 'classfile' => 'import_links_class.php', 'classname' => 'links_import'), - 'media' => array('message' => "Media", 'classfile' => 'import_media_class.php', 'classname' => 'media_import'), - 'comments' => array('message'=> "Comments"), -// 'forumdefs' => array('message' => LAN_CONVERT_26), -// 'forumposts' => array('message' => LAN_CONVERT_48), -// 'polls' => array('message' => LAN_CONVERT_27) -); - - -// See what DB-based imports are available (don't really want it here, but gets it into the header script) -require_once(e_HANDLER.'file_class.php'); - -$fl = new e_file; -$importClassList = $fl->get_files(e_PLUGIN.'import/providers', "^.+?_import_class\.php$", "standard", 1); -foreach($importClassList as $file) -{ - $tag = str_replace('_class.php','',$file['fname']); - include_once($file['path'].$file['fname']); // This will set up the variables -} -unset($importClassList); -unset($fl); -asort($import_class_names); - - - -if(varset($_POST['import_source'])) -{ - $import_source = varset($_POST['import_source'],'csv'); - if(varset($_POST['classes_select'])) - { - $checked_class_list = implode(',',$_POST['classes_select']); - } - $import_delete_existing_data = varset($_POST['import_delete_existing_data'],0); - - $current_csv = varset($_POST['csv_format'],'default'); - $csv_pw_not_encrypted = varset($_POST['csv_pw_not_encrypted'],0); - $csv_data_file = varset($_POST['csv_data_file'],'import.csv'); - - $current_db_type = varset($_POST['db_import_type'],key($import_class_names)); -} - -$db_blocks_to_import = array(); - - -foreach ($db_import_blocks as $k => $v) -{ - if (isset($_POST['import_block_'.$k])) - { - $db_blocks_to_import[$k] = 1; - } -} - -// require_once(e_ADMIN."auth.php"); - -if (!is_object($e_userclass)) -{ - require_once(e_HANDLER."userclass_class.php"); // Modified class handler - $e_userclass = new user_class; -} - - - - -define('CSV_DEF_FILE','csv_import.txt'); // Supplementary CSV format definitions - -// Definitions of available CSV-based imports -$csv_formats = array('default' => 'user_name,user_password'); -$csv_names = array('default' => LAN_CONVERT_12); -$csv_options = array('default' => 'simple'); -$csv_option_settings = array( - 'simple' => array('separator' => ',', 'envelope' => ''), - 'simple_sq' => array('separator' => ',', 'envelope' => "'"), - 'simple_dq' => array('separator' => ',', 'envelope' => '"'), - 'simple_semi' => array('separator' => ',', 'envelope' => ';'), - 'simple_bar' => array('separator' => ',', 'envelope' => '|') - ); - -// See what CSV format definitions are available -if (is_readable(CSV_DEF_FILE)) -{ - $csv_temp = file(CSV_DEF_FILE); - foreach ($csv_temp as $line) - { - $line = trim(str_replace("\n","",$line)); - if ($line) - { - list($temp,$name,$options,$line) = explode(',',$line,4); - $temp = trim($temp); - $name = trim($name); - $options = trim($options); - $line = trim($line); - if ($temp && $name && $options && $line) - { - $csv_formats[$temp] = $line; // Add any new definitions - $csv_names[$temp] = $name; - $csv_options[$temp] = $options; - } - } - } - unset($csv_temp); -} - - - -$msg = ''; - -//====================================================== -// Executive routine - actually do conversion -//====================================================== -if(isset($_POST['do_conversion'])) -{ - $abandon = TRUE; - - switch ($import_source) - { - case 'csv' : - if (!isset($csv_formats[$current_csv])) $msg = "CSV File format error

"; - if (!is_readable($csv_data_file)) $msg = LAN_CONVERT_31; - if (!isset($csv_options[$current_csv])) $msg = LAN_CONVERT_37.' '.$current_csv; - if (!isset($csv_option_settings[$csv_options[$current_csv]])) - { - $msg = LAN_CONVERT_37.' '.$csv_options[$current_csv]; - } - - if (!$msg) - { - $field_list = explode(',',$csv_formats[$current_csv]); - $separator = $csv_option_settings[$csv_options[$current_csv]]['separator']; - $enveloper = $csv_option_settings[$csv_options[$current_csv]]['envelope']; - if (IMPORT_DEBUG) echo "CSV import: {$current_csv} Fields: {$csv_formats[$current_csv]}
"; - require_once('import_user_class.php'); - $usr = new user_import; - $usr->overrideDefault('user_class',$checked_class_list); - if (($source_data = file($csv_data_file)) === FALSE) $msg = LAN_CONVERT_32; - if ($import_delete_existing_data) $usr->emptyTargetDB(); // Delete existing users - reasonably safe now - $line_counter = 0; - $error_counter = 0; - $write_counter = 0; - foreach ($source_data as $line) - { - $line_counter++; - $line_error = FALSE; - if ($line = trim($line)) - { - $usr_data = $usr->getDefaults(); // Reset user data - $line_data = csv_split($line, $separator, $enveloper); - $field_data = current($line_data); - foreach ($field_list as $f) - { - if ($field_data === FALSE) $line_error = TRUE; - if ($f != 'dummy') $usr_data[$f] = $field_data; - $field_data = next($line_data); - } - if ($line_error) - { - if ($msg) $msg .= "
"; - $msg .= LAN_CONVERT_33.$line_counter; - $error_counter++; - } - else - { - if ($csv_pw_not_encrypted) - { - $usr_data['user_password'] = md5($usr_data['user_password']); - } - $line_error = $usr->saveData($usr_data); - if ($line_error === TRUE) - { - $write_counter++; - } - else - { - $line_error = $usr->getErrorText($line_error); - if ($msg) $msg .= "
"; - $msg .= str_replace('--ERRNUM--',$line_error,LAN_CONVERT_34).$line_counter; - $error_counter++; - } - } - } - } - - if ($msg) $msg .= "
"; - if ($import_delete_existing_data) $msg .= LAN_CONVERT_40.'
'; - $msg .= str_replace(array('--LINES--','--USERS--', '--ERRORS--'),array($line_counter,$write_counter,$error_counter),LAN_CONVERT_35); - } - break; - - case 'db' : - if(dbImport() == false) - { - $abandon = true; - } - break; - - case 'rss' : - if(rssImport() == false) - { - $abandon = true; - } - break; - } - - if ($msg) - { - $mes->add($msg, E_MESSAGE_INFO); // $ns -> tablerender(LAN_CONVERT_30, $msg); - $msg = ''; - } - - if ($abandon) - { - // unset($_POST['do_conversion']); - $text = " -
-
- ".$frm->admin_button('dummy_continue',LAN_CONTINUE, 'execute')." -
-
"; - $ns -> tablerender(LAN_CONVERT_30,$mes->render(). $text); - require_once(e_ADMIN."footer.php"); - exit; - } -} -*/ -/* - -function rssImport() -{ - global $current_db_type, $db_import_blocks, $import_delete_existing_data,$db_blocks_to_import; - - $mes = e107::getMessage(); - $mes->addDebug("Loading: RSS"); - if(!varset($_POST['do_conversion'])) - { - $mes->addWarning("Under Construction"); - } - - return dbImport('xml'); - -} - -function dbImport($mode='db') -{ - global $current_db_type, $db_import_blocks, $import_delete_existing_data,$db_blocks_to_import; - - $mes = e107::getMessage(); - - // if (IMPORT_DEBUG) echo "Importing: {$current_db_type}
"; - $mes->addDebug("Loading: ".$current_db_type); - - if (class_exists($current_db_type)) - { - $mes->addDebug("Class Available: ".$current_db_type); - $converter = new $current_db_type; - $converter->init(); - } - else - { - $mes->addError(LAN_CONVERT_42. "[".$current_db_type."]"); - return false; - } - - if($mode == 'db') // Don't do DB check on RSS/XML - { - if (!isset($_POST['dbParamHost']) || !isset($_POST['dbParamUsername']) || !isset($_POST['dbParamPassword']) || !isset($_POST['dbParamDatabase'])) - { - $mes->addError(LAN_CONVERT_41); - return false; - } - - $result = $converter->db_Connect($_POST['dbParamHost'], $_POST['dbParamUsername'], $_POST['dbParamPassword'], $_POST['dbParamDatabase'], $_POST['dbParamPrefix']); - if ($result !== TRUE) - { - $mes->addError(LAN_CONVERT_43.": ".$result); // db connect failed - return false; - } - } - - if(!is_array($db_import_blocks)) - { - $mes->addError("No areas selected for import"); // db connect failed - return false; - } - - if(vartrue($converter->override)) - { - return; - } - - - - foreach ($db_import_blocks as $k => $v) - { - if (isset($db_blocks_to_import[$k])) - { - $loopCounter = 0; - $errorCounter = 0; - - if (is_readable($v['classfile'])) - { - require_once($v['classfile']); - } - else - { - $mes->addError(LAN_CONVERT_45.': '.$v['classfile']); // can't read class file. - return false; - } - - if (varset($_POST["import_block_{$k}"],0) == 1) - { - //if (IMPORT_DEBUG) echo "Importing: {$k}
"; - $mes->addDebug("Importing: ".$k); - - $result = $converter->setupQuery($k,!$import_delete_existing_data); - - if ($result !== TRUE) - { - $mes->addError(LAN_CONVERT_44.' '.$k); // couldn't set query - // $msg .= "Prefix = ".$converter->DBPrefix; - break; - } - - $exporter = new $v['classname']; // Writes the output data - - switch ($k) // Do any type-specific default setting - { - case 'users' : - $exporter->overrideDefault('user_class',$checked_class_list); - break; - } - - if ($import_delete_existing_data) - { - $exporter->emptyTargetDB(); // Clean output DB - reasonably safe now - } - - while ($row = $converter->getNext($exporter->getDefaults(),$mode)) - { - $loopCounter++; - $result = $exporter->saveData($row); - if ($result !== TRUE) - { - $errorCounter++; - $line_error = $exporter->getErrorText($result); - // if ($msg) $msg .= "
"; - $msg = str_replace(array('--ERRNUM--','--DB--'),array($line_error,$k),LAN_CONVERT_46).$loopCounter; - $mes->addError($msg); // couldn't set query - } - } - - $converter->endQuery(); - - unset($exporter); - - - $msg = str_replace(array('--LINES--','--USERS--', '--ERRORS--','--BLOCK--'), - array($loopCounter,$loopCounter-$errorCounter,$errorCounter, $k),LAN_CONVERT_47); - $mes->addSuccess($msg); // couldn't set query - } - else - { - $mes->addDebug("Error: _POST['import_block_{$k}'] = ".$_POST['import_block_{$k}']); // cou - - } - } - else - { - $mes->addDebug("\$db_blocks_to_import doesn't contain key: ".$k); // cou - - } - } - -// $msg = LAN_CONVERT_29; - return true; - // $abandon = FALSE; -} -*/ - -//====================================================== -// Display front page -//====================================================== -new import_admin(); -require_once(e_ADMIN."auth.php"); -e107::getAdminUI()->runPage(); - -require_once(e_ADMIN."footer.php"); - exit; - - - - -/* - * Currently unused function - shows available import methods and capabilities - */ -/* -function showStartPage() -{ - global $emessage, $frm, $import_class_names, $import_class_support, $db_import_blocks, $import_class_comment; - - $frm = e107::getForm(); - - - $text = " -
-
- ".'DBLAN_10'." - ".$frm->hidden('mode','main')." - ".$frm->hidden('action','import')." - - - - - - - - - - - "; - foreach($db_import_blocks as $name) // 1 column for each of users, news, forum etc. - { - $text .= ""; - } - - $text.=" - - - - - - - - - "; - - for ($i=0; $i < count($db_import_blocks)-1; $i++) - { - $text .= ""; - } - - - $text .= ""; - - - foreach ($import_class_names as $k => $title) - { - $iconFile = e_PLUGIN."import/images/".str_replace("_import","",strtolower($k)).".png"; - $icon = (file_exists($iconFile)) ? "" : ""; - - $text .= " - \n"; - - foreach($db_import_blocks as $key=>$val) - { - $text .= "\n"; - } - - $text .= " - - "; - } - - - $text .= " - -
".LAN_CONVERT_06."".$name['message']."".LAN_OPTIONS."
CSV".ADMIN_TRUE_ICON." ".$frm->admin_button('import_type', 'csv', 'other',"Select")."
".$icon.$title."
".$import_class_comment[$k]."
".(in_array($key,$import_class_support[$k]) ? ADMIN_TRUE_ICON : " ").""; - - $text .= $frm->admin_button('type', $k, 'other',"Select"); - // $text .= $frm->admin_button('import_type', $k, 'other',"Select"); - - $text .= " -
-
- ".$frm->hidden('trigger_import',1)." - -
-
-
"; - - echo $emessage->render().$text; - // $ns->tablerender(LAN_PLUGIN_IMPORT_NAME, $emessage->render().$text); - -} - - - - -function showImportOptions($mode='csv') -{ - global $text, $emessage, $csv_names, $import_class_names, $e_userclass, $db_import_blocks, $import_class_support, $import_default_prefix; - - $frm = e107::getForm(); - $ns = e107::getRender(); - - $mes = e107::getMessage(); - - if (class_exists($mode)) - { - $mes->addDebug("Class Available: ".$mode); - $proObj = new $mode; - if($proObj->init()===FALSE) - { - return; - } - } - - $message = "".LAN_CONVERT_05.""; - $emessage->add($message, E_MESSAGE_WARNING); - - $text = " -
- - - - - "; - - if($mode == "csv") - { - $text .= " - - - - - - - - - - - - - - "; - - } - elseif(method_exists($proObj,"config")) - { - $ops = $proObj->config(); - foreach($ops as $key=>$val) - { - $text .= " - - - \n"; - } - - if($proObj->sourceType) - { - $text .= "\n"; - } - - } - else - { - $importType = $import_class_names[$mode]; - - $text .= " - - - - - - - - - - - - - - - - - - - - "; - - } - - if($mode != 'csv') - { - $text .= " - - - "; - } - - - $text .= " - - "; - - if(varset($proObj->defaultClass) !== false) - { - $text .= " - - "; - } - - $action = varset($proObj->action,'do_conversion'); - $text .= "
".LAN_CONVERT_07."\n -
".LAN_CONVERT_36."
".LAN_CONVERT_17." - - - - - ".LAN_CONVERT_18."
".$val['caption']."".$val['html']; - $text .= (vartrue($val['help'])) ? "
".$val['help']."
" : ""; - $text .= "
$importType ".LAN_CONVERT_19."
$importType ".LAN_CONVERT_20."
$importType ".LAN_CONVERT_21."
$importType ".LAN_CONVERT_22."
$importType ".LAN_CONVERT_23." - -
$importType ".LAN_CONVERT_24.""; - - $defCheck = (count($import_class_support[$mode])==1) ? "checked='checked'" : ""; - foreach ($db_import_blocks as $k => $v) - { - if(in_array($k, $import_class_support[$mode])) // display only the options supported. - { - $text .= " ".$v['message']; - $text .= "
"; - } - } - $text .= "
".LAN_CONVERT_38." - ".LAN_CONVERT_39."
".LAN_CONVERT_16.""; - $text .= $e_userclass->vetted_tree('classes_select',array($e_userclass,'checkbox'), varset($_POST['classes_select']),'main,admin,classes,matchclass, no-excludes'); - $text .= "
-
".$frm->admin_button($action,LAN_CONTINUE, 'execute'). - - $frm->admin_button('back',LAN_CANCEL, 'cancel')." - - -
-
"; - - // Now a little bit of JS to initialise some of the display divs etc - $temp = ''; - if(varset($import_source)) { $temp .= "disp('{$import_source}');"; } - if (varset($current_db_type)) $temp .= " flagbits('{$current_db_type}');"; - if (varset($temp)) $text .= ""; - - $ns -> tablerender(LAN_PLUGIN_IMPORT_NAME.SEP.$importType, $emessage->render().$text); - -} -*/ - - - - - -function csv_split(&$data,$delim=',',$enveloper='') -{ - $ret_array = array(); - $fldval=''; - $enclosed = false; -// $fldcount=0; -// $linecount=0; - for($i=0;$i $val) - { - $blocks .= "block_names[{$i}]='{$it}';\n"; - $i++; - } - - $i = 0; - foreach ($import_class_support as $k => $v) - { - $vals .= "db_names[$i] = '{$k}';\n"; - $comments .= "comment_text[$i] = '{$import_class_comment[$k]}';\n"; -// $temp = $import_class_support[$k]; // Array of import types supported - $j = 0; - $m = 1; // Mask bit - foreach ($db_import_blocks as $it => $val) - { - if (in_array($it,$v)) $j = $j + $m; - $m = $m + $m; - } - $texts .= "db_options[{$i}] = {$j};\n"; - $i++; - } - - $text = " - "; - - return $text; -} - - - -?> + array( + 'controller' => 'import_main_ui', + 'path' => null, + 'ui' => 'import_admin_form_ui', + 'uipath' => null + ), + 'cat' => array( + 'controller' => 'import_cat_ui', + 'path' => null, + 'ui' => 'import_cat_form_ui', + 'uipath' => null + ) + ); + + protected $adminMenu = array( + 'main/list' => array('caption'=> LAN_LIST, 'perm' => '0'), + // 'main/create' => array('caption'=> 'Create import', 'perm' => '0'), +// 'cat/list' => array('caption'=> 'Categories', 'perm' => '0'), +// 'cat/create' => array('caption'=> "Create Category", 'perm' => '0'), + // 'main/prefs' => array('caption'=> LAN_PREFS, 'perm' => '0'), + // 'main/custom' => array('caption'=> 'Custom Page', 'perm' => '0') + ); + + protected $adminMenuAliases = array( + 'main/edit' => 'main/list' + ); + + protected $menuTitle = LAN_PLUGIN_IMPORT_NAME; +} + + +class import_main_ui extends e_admin_ui +{ + + protected $pluginTitle = LAN_PLUGIN_IMPORT_NAME; + protected $pluginName = 'import'; + protected $table = false; + + protected $providers = array(); // the different types of import. + protected $deleteExisting = false; // delete content from existing table during import. + protected $selectedTables = array(); // User selection of what tables to import. eg. news, pages etc. + protected $importClass = null; + protected $checked_class_list = ''; + + // Definitions of available areas to import + protected $importTables = array( + 'users' => array('message' => LAN_CONVERT_25, 'classfile' => 'import_user_class.php', 'classname' => 'user_import'), + 'userclass' => array('message' => LAN_CONVERT_73, 'nolist'=>true, 'classfile' => 'import_user_class.php', 'classname' => 'userclass_import'), + + 'news' => array('message' => LAN_CONVERT_28, 'classfile' => 'import_news_class.php', 'classname' => 'news_import'), + 'newscategory' => array('message' => LAN_CONVERT_74, 'nolist'=>true, 'classfile' => 'import_news_class.php', 'classname' => 'newscategory_import'), + + 'page' => array('message' => LAN_CONVERT_65, 'classfile' => 'import_page_class.php', 'classname' => 'page_import'), + 'pagechapter' => array('message' => LAN_CONVERT_66, 'nolist'=>true, 'classfile' => 'import_page_class.php', 'classname' => 'pagechapter_import'), + 'links' => array('message' => LAN_CONVERT_67, 'classfile' => 'import_links_class.php', 'classname' => 'links_import'), + 'media' => array('message' => LAN_CONVERT_68, 'classfile' => 'import_media_class.php', 'classname' => 'media_import'), + 'forum' => array('message' => LAN_CONVERT_69, 'classfile' => 'import_forum_class.php', 'classname' => 'forum_import'), + 'forumthread' => array('message' => LAN_CONVERT_70, 'classfile' => 'import_forum_class.php', 'classname' => 'forumthread_import', 'nolist'=>true), + 'forumpost' => array('message' => LAN_CONVERT_71, 'classfile' => 'import_forum_class.php', 'classname' => 'forumpost_import', 'nolist'=>true), + 'forumtrack' => array('message' => LAN_CONVERT_72, 'classfile' => 'import_forum_class.php', 'classname' => 'forumtrack_import', 'nolist'=>true), + // 'comments' => array('message'=> LAN_COMMENTS), + + // 'polls' => array('message' => LAN_CONVERT_27) + ); + + // without any Order or Limit. + + + + function init() + { + $fl = e107::getFile(); + + $importClassList = $fl->get_files(e_PLUGIN.'import/providers', "^.+?_import_class\.php$", "standard", 1); + + foreach($importClassList as $file) + { + + + $tag = str_replace('_class.php','',$file['fname']); + + $key = str_replace("_import_class.php","",$file['fname']); + + if($key === 'template') + { + continue; + } + + include_once($file['path'].$file['fname']); // This will set up the variables + + $this->providers[$key] = $this->getMeta($tag); + + if(!empty($_GET['type'])) + { + $this->importClass = filter_var($_GET['type'])."_import"; + } + + } + + + uksort($this->providers,'strcasecmp'); + + + } + + + function help() + { + + return "Some help text for admin-ui"; + + } + + + + + + function getMeta($class_name) + { + if(class_exists($class_name)) + { + $obj = new $class_name; + return array('title' => vartrue($obj->title), 'description' => vartrue($obj->description), 'supported' => vartrue($obj->supported)); + } + else + { + e107::getMessage()->addDebug("Missing class: ".$class_name); + } + + } + + + + + + // After selection - decide where to route things. + function importPage() + { + + // print_a($_POST); + + if(!empty($_POST['import_delete_existing_data'])) + { + $this->deleteExisting = varset($_POST['import_delete_existing_data'],0); + } + + if(!empty($_POST['classes_select'])) + { + $this->checked_class_list = implode(',',$_POST['classes_select']); + } + + if(!empty($_POST['createUserExtended'])) //TODO + { + $this->createUserExtended = true; + } + + if(!empty($_POST['selectedTables'])) + { + $this->selectedTables = $_POST['selectedTables']; + } + + if(!empty($_POST['runConversion'])) // default method. + { + $this->runConversion($_POST['import_source']); + return; + } + + + + + $this->showImportOptions($_GET['type']); + + } + + + + + + + + + + function listPage() + { + $mes = e107::getMessage(); + $frm = e107::getForm(); + + $tableCount = 0; + // $mes->addDebug(print_a($this->providers,true)); + + $text = " +
+
+ ".'DBLAN_10'." + ".$frm->hidden('mode','main')." + ".$frm->hidden('action','import')." + + + "; + + foreach($this->importTables as $key=>$val) + { + if(!empty($val['nolist'])){ continue; } + $text .= "\n"; + } + + + $text .= " + + + + + + "; + foreach($this->importTables as $val) // 1 column for each of users, news, forum etc. + { + if(vartrue($val['nolist'])){ continue; } + $text .= ""; + $tableCount++; + } + + $text.=" + + + + + "; + /* + $text .= " + + + + "; + + for ($i=0; $i < $tableCount-1; $i++) + { + $text .= ""; + } + + + $text .= ""; + */ + + foreach ($this->providers as $k=>$info) + { + $title = $info['title']; + + $iconFile = e_PLUGIN."import/images/".str_replace("_import","",strtolower($k)).".png"; + + $icon = (file_exists($iconFile)) ? "" : ""; + + $text .= " + \n"; + + foreach($this->importTables as $key=>$val) + { + if(vartrue($val['nolist'])){ continue; } + $text .= "\n"; + } + + $text .= " + + "; + } + + + $text .= " + +
".LAN_CONVERT_06."".$val['message']."".LAN_OPTIONS."
CSV".ADMIN_TRUE_ICON." ".$frm->admin_button('import_type', 'csv', 'other',"Select")."
".$icon.$title."
".$info['description']."
".(in_array($key,$info['supported']) ? ADMIN_TRUE_ICON : " ").""; + + $text .= $frm->admin_button('type', $k, 'other',LAN_CONVERT_64); + // $text .= $frm->admin_button('import_type', $k, 'other',"Select"); + + $text .= " +
+
+ ".$frm->hidden('trigger_import',1)." + +
+
+
"; + + echo $mes->render().$text; + // $ns->tablerender(LAN_PLUGIN_IMPORT_NAME, $mes->render().$text); + + } + + + + + + function runConversion($import_source) + { + $frm = e107::getForm(); + $ns = e107::getRender(); + $mes = e107::getMessage(); + + $abandon = TRUE; + + switch ($import_source) + { + case 'csv' : + + break; + + case 'db' : + if($this->dbImport() == false) + { + $abandon = true; + } + break; + + case 'rss' : + if($this->rssImport() == false) + { + $abandon = true; + } + break; + } + + +// if ($msg) +// { +// $mes->add($msg, E_MESSAGE_INFO); // $ns -> tablerender(LAN_CONVERT_30, $msg); +// $msg = ''; +// } + + if ($abandon) + { + // unset($_POST['do_conversion']); + $text = " +
+
+ ".$frm->admin_button('dummy_continue',LAN_CONTINUE, 'execute')." +
+
"; + echo $mes->render(). $text; + + // $ns -> tablerender(LAN_CONVERT_30,$mes->render(). $text); + + } + } + + + + + function renderConfig() + { + + } + + + + + + + + + function showImportOptions($type='csv') + { + global $csv_names, $e_userclass; + $mode = $this->importClass; + + $frm = e107::getForm(); + $ns = e107::getRender(); + + $mes = e107::getMessage(); + + if (class_exists($mode)) + { + $mes->addDebug("Class Available: ".$mode); + $proObj = new $mode; + if($proObj->init()===FALSE) + { + return; + } + } + + $message = "".LAN_CONVERT_05.""; + $mes->add($message, E_MESSAGE_WARNING); + + $text = " +
+ + + + + "; + + + + /* + if($mode == "csv") + { + $text .= " + + + + + + + + + + + + + + "; + + } + else + */ + + $importType = $proObj->title; + + if($proObj->sourceType == 'db' || !$proObj->sourceType) // STANDARD db Setup + { + $databases = $this->getDatabases(); + $prefix = (varset($_POST['dbParamPrefix']) ? $_POST['dbParamPrefix'] : $proObj->mprefix); + /* + $text .= " + + + + + + + + + + + + + ";*/ + + $text .= " + + + + + + + + "; + + } + + + if(method_exists($proObj,"config")) // Config Found in Class - render options from it. + { + if($ops = $proObj->config()) + { + foreach($ops as $key=>$val) + { + $text .= " + + + \n"; + } + } + } + + + if($proObj->sourceType) + { + $text .= "\n"; + } + else + { + $text .= ""; + } + + + + + // if($mode != 'csv') + { + $text .= " + + + "; + } + + + $text .= " + + + + "; + + //TODO + /* + if(in_array('users',$proObj->supported)) + { + $text .= " + + + "; + } + */ + + if(varset($proObj->defaultClass) !== false) + { + $text .= " + + "; + } + + $action = varset($proObj->action,'runConversion'); + $text .= "
".LAN_CONVERT_07."\n +
".LAN_CONVERT_36."
".LAN_CONVERT_17." + + + + + ".LAN_CONVERT_18."
$importType ".LAN_CONVERT_19."
$importType ".LAN_CONVERT_20." + +
Must be different from the one e107 uses.
+
$importType ".LAN_CONVERT_21."
$importType ".LAN_CONVERT_22."".$frm->select('dbParamDatabase', $databases, null, array('required'=>1), LAN_SELECT."...")."
$importType ".LAN_CONVERT_23."".$frm->text('dbParamPrefix', $prefix, 100)." + +
".$val['caption']."".$val['html']; + $text .= (vartrue($val['help'])) ? "
".$val['help']."
" : ""; + $text .= "
$importType ".LAN_CONVERT_24.""; + + $defCheck = (count($proObj->supported)==1) ? true : false; + foreach ($this->importTables as $k => $v) + { + if(in_array($k, $proObj->supported)) // display only the options supported. + { + $text .= $frm->checkbox('selectedTables['.$k.']', $k, $defCheck,array('label'=>$v['message'])); + + + //$text .= " ".$v['message']; + // $text .= "
"; + } + } + $text .= "
".LAN_CONVERT_38."".$frm->radio_switch('import_delete_existing_data', $_POST['import_delete_existing_data'])." +
".LAN_CONVERT_39."
Create Extended User Fields".$frm->checkbox('createUserExtended', 1,'', array('label'=>' ','title'=>'Will automatically add missing user-fields when found.'))." +
".LAN_CONVERT_16.""; + $text .= $e_userclass->vetted_tree('classes_select',array($e_userclass,'checkbox'), varset($_POST['classes_select']),'main,admin,classes,matchclass, no-excludes'); + $text .= "
+
".$frm->admin_button($action,LAN_CONTINUE, 'execute'). + + $frm->admin_button('back',LAN_CANCEL, 'cancel')." + + +
+
"; + + // Now a little bit of JS to initialise some of the display divs etc + // $temp = ''; + // if(varset($import_source)) { $temp .= "disp('{$import_source}');"; } + // if (varset($current_db_type)) $temp .= " flagbits('{$current_db_type}');"; + // if (varset($temp)) $text .= ""; + + $this->addTitle($importType); + echo $mes->render().$text; + + // $ns -> tablerender(LAN_PLUGIN_IMPORT_NAME.SEP.$importType, $mes->render().$text); + + } + + + private function getDatabases() + { + $tmp = e107::getDb()->gen("SHOW DATABASES"); + $databases = e107::getDb()->db_getList(); + + $arr = array(); + + $exclude = array('mysql', 'information_schema', 'performance_schema', 'phpmyadmin'); + + foreach($databases as $v) + { + $id = $v['Database']; + + if(in_array($id,$exclude)) + { + continue; + } + + $arr[$id] = $id; + + } + + return $arr; + + + } + + + + function rssImport() + { + global $current_db_type; + + $mes = e107::getMessage(); + $mes->addDebug("Loading: RSS"); + + if(!varset($_POST['runConversion'])) + { + $mes->addWarning("Under Construction"); + } + + return $this->dbImport('xml'); + + } + + + + /** MAIN IMPORT AREA */ + function dbImport($mode='db') + { + + $mes = e107::getMessage(); + $tp = e107::getParser(); + + $mes->addDebug("dbImport(): Loading: ".$this->importClass); + + if(!is_array($this->importTables)) + { + $mes->addError("dbImport(): No areas selected for import"); // db connect failed + return false; + } + + if (class_exists($this->importClass)) + { + $mes->addDebug("dbImport(): Converter Class Available: ".$this->importClass); + $converter = new $this->importClass ; + $converter->init(); + } + else + { + $mes->addError(LAN_CONVERT_42. "[".$this->importClass."]"); + $mes->addDebug("dbImport(): Class NOT Available: ".$this->importClass); + + return false; + } + + + if($mode == 'db') // Don't do DB check on RSS/XML + { + if (empty($_POST['dbParamDatabase'])) + { + $mes->addError(LAN_CONVERT_41); + return false; + } + + $result = $converter->database($tp->filter($_POST['dbParamDatabase']), $tp->filter($_POST['dbParamPrefix'])); + + // $result = $converter->database($tp->filter($_POST['dbParamDatabase']), $tp->filter($_POST['dbParamPrefix']), true); + + if ($result !== true) + { + $mes->addError(LAN_CONVERT_43.": ".$result); // db connect failed + return false; + } + } + + + if(vartrue($converter->override)) + { + $mes->addDebug("dbImport(): Override Active!" ); + return; + } + + + + // Return + foreach($this->selectedTables as $k => $tm) + { + $v = $this->importTables[$k]; + + $loopCounter = 0; + $errorCounter = 0; + + if (is_readable($v['classfile'])) // Load our class for either news, pages etc. + { + $mes->addDebug("dbImport(): Including File: ".$v['classfile']); + require_once($v['classfile']); + } + else + { + $mes->addError(LAN_CONVERT_45.': '.$v['classfile']); // can't read class file. + return false; + } + + $mes->addDebug("dbImport(): Importing: ".$k); + + $exporter = new $v['classname']; // Writes the output data + + if(is_object($exporter)) + { + $mes->addDebug("dbImport(): Exporter Class Initiated: ".$v['classname']); + + if(is_object($exporter->helperClass)) + { + $mes->addDebug("dbImport(): Initiated Helper Class"); + $converter->helperClass = $exporter->helperClass; + } + + } + else + { + $mes->addDebug("dbImport(): Couldn't Initiate Class: ".$v['classname']); + } + + + $result = $converter->setupQuery($k, !$this->deleteExisting); + + if ($result !== true) + { + $mes->addError(LAN_CONVERT_44.' '.$k); // couldn't set query + break; + } + + + + + if($k == 'users') // Do any type-specific default setting + { + $mes->addDebug("dbImport(): Overriding Default for user_class: ".$this->checked_class_list); + $exporter->overrideDefault('user_class', $this->checked_class_list); + // break; + } + + if ($this->deleteExisting == true) + { + $mes->addDebug("dbImport(): Emptying target table. "); + $exporter->emptyTargetDB(); // Clean output DB - reasonably safe now + } + + while ($row = $converter->getNext($exporter->getDefaults(),$mode)) + { + $loopCounter++; + $result = $exporter->saveData($row); + if ($result !== TRUE) + { + $errorCounter++; + $line_error = $exporter->getErrorText($result); + // if ($msg) $msg .= "
"; + $msg = str_replace(array('[x]','[y]'),array($line_error,$k),LAN_CONVERT_46).$loopCounter; + $mes->addError($msg); // couldn't set query + } + } + + $converter->endQuery(); + + unset($exporter); + + + $msg = str_replace(array('[x]','[y]', '[z]','[w]'), + array($loopCounter,$loopCounter-$errorCounter,$errorCounter, $k),LAN_CONVERT_47); + $mes->addSuccess($msg); // couldn't set query + } + + + + + + + + + + + return true; + + // $abandon = FALSE; + } + + + + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* + +// Source DB types (i.e. CMS types) supported. Key of each element is the 'short code' for the type +$import_class_names = array(); // Title +$import_class_comment = array(); // Descriptive comment +$import_class_support = array(); // Array of data types supported + +// Definitions of available areas to import +$db_import_blocks = array( + 'users' => array('message' => LAN_CONVERT_25, 'classfile' => 'import_user_class.php', 'classname' => 'user_import'), + 'news' => array('message' => LAN_CONVERT_28, 'classfile' => 'import_news_class.php', 'classname' => 'news_import'), + 'page' => array('message' => "Pages", 'classfile' => 'import_page_class.php', 'classname' => 'page_import'), + 'links' => array('message' => "Links", 'classfile' => 'import_links_class.php', 'classname' => 'links_import'), + 'media' => array('message' => "Media", 'classfile' => 'import_media_class.php', 'classname' => 'media_import'), + 'comments' => array('message'=> "Comments"), +// 'forumdefs' => array('message' => LAN_CONVERT_26), +// 'forumposts' => array('message' => LAN_CONVERT_48), +// 'polls' => array('message' => LAN_CONVERT_27) +); + + +// See what DB-based imports are available (don't really want it here, but gets it into the header script) +require_once(e_HANDLER.'file_class.php'); + +$fl = new e_file; +$importClassList = $fl->get_files(e_PLUGIN.'import/providers', "^.+?_import_class\.php$", "standard", 1); +foreach($importClassList as $file) +{ + $tag = str_replace('_class.php','',$file['fname']); + include_once($file['path'].$file['fname']); // This will set up the variables +} +unset($importClassList); +unset($fl); +asort($import_class_names); + + + +if(varset($_POST['import_source'])) +{ + $import_source = varset($_POST['import_source'],'csv'); + if(varset($_POST['classes_select'])) + { + $checked_class_list = implode(',',$_POST['classes_select']); + } + $import_delete_existing_data = varset($_POST['import_delete_existing_data'],0); + + $current_csv = varset($_POST['csv_format'],'default'); + $csv_pw_not_encrypted = varset($_POST['csv_pw_not_encrypted'],0); + $csv_data_file = varset($_POST['csv_data_file'],'import.csv'); + + $current_db_type = varset($_POST['db_import_type'],key($import_class_names)); +} + +$db_blocks_to_import = array(); + + +foreach ($db_import_blocks as $k => $v) +{ + if (isset($_POST['import_block_'.$k])) + { + $db_blocks_to_import[$k] = 1; + } +} + +// require_once(e_ADMIN."auth.php"); + +if (!is_object($e_userclass)) +{ + require_once(e_HANDLER."userclass_class.php"); // Modified class handler + $e_userclass = new user_class; +} + + + + +define('CSV_DEF_FILE','csv_import.txt'); // Supplementary CSV format definitions + +// Definitions of available CSV-based imports +$csv_formats = array('default' => 'user_name,user_password'); +$csv_names = array('default' => LAN_CONVERT_12); +$csv_options = array('default' => 'simple'); +$csv_option_settings = array( + 'simple' => array('separator' => ',', 'envelope' => ''), + 'simple_sq' => array('separator' => ',', 'envelope' => "'"), + 'simple_dq' => array('separator' => ',', 'envelope' => '"'), + 'simple_semi' => array('separator' => ',', 'envelope' => ';'), + 'simple_bar' => array('separator' => ',', 'envelope' => '|') + ); + +// See what CSV format definitions are available +if (is_readable(CSV_DEF_FILE)) +{ + $csv_temp = file(CSV_DEF_FILE); + foreach ($csv_temp as $line) + { + $line = trim(str_replace("\n","",$line)); + if ($line) + { + list($temp,$name,$options,$line) = explode(',',$line,4); + $temp = trim($temp); + $name = trim($name); + $options = trim($options); + $line = trim($line); + if ($temp && $name && $options && $line) + { + $csv_formats[$temp] = $line; // Add any new definitions + $csv_names[$temp] = $name; + $csv_options[$temp] = $options; + } + } + } + unset($csv_temp); +} + + + +$msg = ''; + +//====================================================== +// Executive routine - actually do conversion +//====================================================== +if(isset($_POST['do_conversion'])) +{ + $abandon = TRUE; + + switch ($import_source) + { + case 'csv' : + if (!isset($csv_formats[$current_csv])) $msg = "CSV File format error

"; + if (!is_readable($csv_data_file)) $msg = LAN_CONVERT_31; + if (!isset($csv_options[$current_csv])) $msg = LAN_CONVERT_37.' '.$current_csv; + if (!isset($csv_option_settings[$csv_options[$current_csv]])) + { + $msg = LAN_CONVERT_37.' '.$csv_options[$current_csv]; + } + + if (!$msg) + { + $field_list = explode(',',$csv_formats[$current_csv]); + $separator = $csv_option_settings[$csv_options[$current_csv]]['separator']; + $enveloper = $csv_option_settings[$csv_options[$current_csv]]['envelope']; + if (IMPORT_DEBUG) echo "CSV import: {$current_csv} Fields: {$csv_formats[$current_csv]}
"; + require_once('import_user_class.php'); + $usr = new user_import; + $usr->overrideDefault('user_class',$checked_class_list); + if (($source_data = file($csv_data_file)) === FALSE) $msg = LAN_CONVERT_32; + if ($import_delete_existing_data) $usr->emptyTargetDB(); // Delete existing users - reasonably safe now + $line_counter = 0; + $error_counter = 0; + $write_counter = 0; + foreach ($source_data as $line) + { + $line_counter++; + $line_error = FALSE; + if ($line = trim($line)) + { + $usr_data = $usr->getDefaults(); // Reset user data + $line_data = csv_split($line, $separator, $enveloper); + $field_data = current($line_data); + foreach ($field_list as $f) + { + if ($field_data === FALSE) $line_error = TRUE; + if ($f != 'dummy') $usr_data[$f] = $field_data; + $field_data = next($line_data); + } + if ($line_error) + { + if ($msg) $msg .= "
"; + $msg .= LAN_CONVERT_33.$line_counter; + $error_counter++; + } + else + { + if ($csv_pw_not_encrypted) + { + $usr_data['user_password'] = md5($usr_data['user_password']); + } + $line_error = $usr->saveData($usr_data); + if ($line_error === TRUE) + { + $write_counter++; + } + else + { + $line_error = $usr->getErrorText($line_error); + if ($msg) $msg .= "
"; + $msg .= str_replace('--ERRNUM--',$line_error,LAN_CONVERT_34).$line_counter; + $error_counter++; + } + } + } + } + + if ($msg) $msg .= "
"; + if ($import_delete_existing_data) $msg .= LAN_CONVERT_40.'
'; + $msg .= str_replace(array('--LINES--','--USERS--', '--ERRORS--'),array($line_counter,$write_counter,$error_counter),LAN_CONVERT_35); + } + break; + + case 'db' : + if(dbImport() == false) + { + $abandon = true; + } + break; + + case 'rss' : + if(rssImport() == false) + { + $abandon = true; + } + break; + } + + if ($msg) + { + $mes->add($msg, E_MESSAGE_INFO); // $ns -> tablerender(LAN_CONVERT_30, $msg); + $msg = ''; + } + + if ($abandon) + { + // unset($_POST['do_conversion']); + $text = " +
+
+ ".$frm->admin_button('dummy_continue',LAN_CONTINUE, 'execute')." +
+
"; + $ns -> tablerender(LAN_CONVERT_30,$mes->render(). $text); + require_once(e_ADMIN."footer.php"); + exit; + } +} +*/ +/* + +function rssImport() +{ + global $current_db_type, $db_import_blocks, $import_delete_existing_data,$db_blocks_to_import; + + $mes = e107::getMessage(); + $mes->addDebug("Loading: RSS"); + if(!varset($_POST['do_conversion'])) + { + $mes->addWarning("Under Construction"); + } + + return dbImport('xml'); + +} + +function dbImport($mode='db') +{ + global $current_db_type, $db_import_blocks, $import_delete_existing_data,$db_blocks_to_import; + + $mes = e107::getMessage(); + + // if (IMPORT_DEBUG) echo "Importing: {$current_db_type}
"; + $mes->addDebug("Loading: ".$current_db_type); + + if (class_exists($current_db_type)) + { + $mes->addDebug("Class Available: ".$current_db_type); + $converter = new $current_db_type; + $converter->init(); + } + else + { + $mes->addError(LAN_CONVERT_42. "[".$current_db_type."]"); + return false; + } + + if($mode == 'db') // Don't do DB check on RSS/XML + { + if (!isset($_POST['dbParamHost']) || !isset($_POST['dbParamUsername']) || !isset($_POST['dbParamPassword']) || !isset($_POST['dbParamDatabase'])) + { + $mes->addError(LAN_CONVERT_41); + return false; + } + + $result = $converter->db_Connect($_POST['dbParamHost'], $_POST['dbParamUsername'], $_POST['dbParamPassword'], $_POST['dbParamDatabase'], $_POST['dbParamPrefix']); + if ($result !== TRUE) + { + $mes->addError(LAN_CONVERT_43.": ".$result); // db connect failed + return false; + } + } + + if(!is_array($db_import_blocks)) + { + $mes->addError("No areas selected for import"); // db connect failed + return false; + } + + if(vartrue($converter->override)) + { + return; + } + + + + foreach ($db_import_blocks as $k => $v) + { + if (isset($db_blocks_to_import[$k])) + { + $loopCounter = 0; + $errorCounter = 0; + + if (is_readable($v['classfile'])) + { + require_once($v['classfile']); + } + else + { + $mes->addError(LAN_CONVERT_45.': '.$v['classfile']); // can't read class file. + return false; + } + + if (varset($_POST["import_block_{$k}"],0) == 1) + { + //if (IMPORT_DEBUG) echo "Importing: {$k}
"; + $mes->addDebug("Importing: ".$k); + + $result = $converter->setupQuery($k,!$import_delete_existing_data); + + if ($result !== TRUE) + { + $mes->addError(LAN_CONVERT_44.' '.$k); // couldn't set query + // $msg .= "Prefix = ".$converter->DBPrefix; + break; + } + + $exporter = new $v['classname']; // Writes the output data + + switch ($k) // Do any type-specific default setting + { + case 'users' : + $exporter->overrideDefault('user_class',$checked_class_list); + break; + } + + if ($import_delete_existing_data) + { + $exporter->emptyTargetDB(); // Clean output DB - reasonably safe now + } + + while ($row = $converter->getNext($exporter->getDefaults(),$mode)) + { + $loopCounter++; + $result = $exporter->saveData($row); + if ($result !== TRUE) + { + $errorCounter++; + $line_error = $exporter->getErrorText($result); + // if ($msg) $msg .= "
"; + $msg = str_replace(array('--ERRNUM--','--DB--'),array($line_error,$k),LAN_CONVERT_46).$loopCounter; + $mes->addError($msg); // couldn't set query + } + } + + $converter->endQuery(); + + unset($exporter); + + + $msg = str_replace(array('--LINES--','--USERS--', '--ERRORS--','--BLOCK--'), + array($loopCounter,$loopCounter-$errorCounter,$errorCounter, $k),LAN_CONVERT_47); + $mes->addSuccess($msg); // couldn't set query + } + else + { + $mes->addDebug("Error: _POST['import_block_{$k}'] = ".$_POST['import_block_{$k}']); // cou + + } + } + else + { + $mes->addDebug("\$db_blocks_to_import doesn't contain key: ".$k); // cou + + } + } + +// $msg = LAN_CONVERT_29; + return true; + // $abandon = FALSE; +} +*/ + +//====================================================== +// Display front page +//====================================================== +new import_admin(); +require_once(e_ADMIN."auth.php"); +e107::getAdminUI()->runPage(); + +require_once(e_ADMIN."footer.php"); + exit; + + + + +/* + * Currently unused function - shows available import methods and capabilities + */ +/* +function showStartPage() +{ + global $emessage, $frm, $import_class_names, $import_class_support, $db_import_blocks, $import_class_comment; + + $frm = e107::getForm(); + + + $text = " +
+
+ ".'DBLAN_10'." + ".$frm->hidden('mode','main')." + ".$frm->hidden('action','import')." + + + + + + + + + + + "; + foreach($db_import_blocks as $name) // 1 column for each of users, news, forum etc. + { + $text .= ""; + } + + $text.=" + + + + + + + + + "; + + for ($i=0; $i < count($db_import_blocks)-1; $i++) + { + $text .= ""; + } + + + $text .= ""; + + + foreach ($import_class_names as $k => $title) + { + $iconFile = e_PLUGIN."import/images/".str_replace("_import","",strtolower($k)).".png"; + $icon = (file_exists($iconFile)) ? "" : ""; + + $text .= " + \n"; + + foreach($db_import_blocks as $key=>$val) + { + $text .= "\n"; + } + + $text .= " + + "; + } + + + $text .= " + +
".LAN_CONVERT_06."".$name['message']."".LAN_OPTIONS."
CSV".ADMIN_TRUE_ICON." ".$frm->admin_button('import_type', 'csv', 'other',"Select")."
".$icon.$title."
".$import_class_comment[$k]."
".(in_array($key,$import_class_support[$k]) ? ADMIN_TRUE_ICON : " ").""; + + $text .= $frm->admin_button('type', $k, 'other',"Select"); + // $text .= $frm->admin_button('import_type', $k, 'other',"Select"); + + $text .= " +
+
+ ".$frm->hidden('trigger_import',1)." + +
+
+
"; + + echo $emessage->render().$text; + // $ns->tablerender(LAN_PLUGIN_IMPORT_NAME, $emessage->render().$text); + +} + + + + +function showImportOptions($mode='csv') +{ + global $text, $emessage, $csv_names, $import_class_names, $e_userclass, $db_import_blocks, $import_class_support, $import_default_prefix; + + $frm = e107::getForm(); + $ns = e107::getRender(); + + $mes = e107::getMessage(); + + if (class_exists($mode)) + { + $mes->addDebug("Class Available: ".$mode); + $proObj = new $mode; + if($proObj->init()===FALSE) + { + return; + } + } + + $message = "".LAN_CONVERT_05.""; + $emessage->add($message, E_MESSAGE_WARNING); + + $text = " +
+ + + + + "; + + if($mode == "csv") + { + $text .= " + + + + + + + + + + + + + + "; + + } + elseif(method_exists($proObj,"config")) + { + $ops = $proObj->config(); + foreach($ops as $key=>$val) + { + $text .= " + + + \n"; + } + + if($proObj->sourceType) + { + $text .= "\n"; + } + + } + else + { + $importType = $import_class_names[$mode]; + + $text .= " + + + + + + + + + + + + + + + + + + + + "; + + } + + if($mode != 'csv') + { + $text .= " + + + "; + } + + + $text .= " + + "; + + if(varset($proObj->defaultClass) !== false) + { + $text .= " + + "; + } + + $action = varset($proObj->action,'do_conversion'); + $text .= "
".LAN_CONVERT_07."\n +
".LAN_CONVERT_36."
".LAN_CONVERT_17." + + + + + ".LAN_CONVERT_18."
".$val['caption']."".$val['html']; + $text .= (vartrue($val['help'])) ? "
".$val['help']."
" : ""; + $text .= "
$importType ".LAN_CONVERT_19."
$importType ".LAN_CONVERT_20."
$importType ".LAN_CONVERT_21."
$importType ".LAN_CONVERT_22."
$importType ".LAN_CONVERT_23." + +
$importType ".LAN_CONVERT_24.""; + + $defCheck = (count($import_class_support[$mode])==1) ? "checked='checked'" : ""; + foreach ($db_import_blocks as $k => $v) + { + if(in_array($k, $import_class_support[$mode])) // display only the options supported. + { + $text .= " ".$v['message']; + $text .= "
"; + } + } + $text .= "
".LAN_CONVERT_38." + ".LAN_CONVERT_39."
".LAN_CONVERT_16.""; + $text .= $e_userclass->vetted_tree('classes_select',array($e_userclass,'checkbox'), varset($_POST['classes_select']),'main,admin,classes,matchclass, no-excludes'); + $text .= "
+
".$frm->admin_button($action,LAN_CONTINUE, 'execute'). + + $frm->admin_button('back',LAN_CANCEL, 'cancel')." + + +
+
"; + + // Now a little bit of JS to initialise some of the display divs etc + $temp = ''; + if(varset($import_source)) { $temp .= "disp('{$import_source}');"; } + if (varset($current_db_type)) $temp .= " flagbits('{$current_db_type}');"; + if (varset($temp)) $text .= ""; + + $ns -> tablerender(LAN_PLUGIN_IMPORT_NAME.SEP.$importType, $emessage->render().$text); + +} +*/ + + + + + +function csv_split(&$data,$delim=',',$enveloper='') +{ + $ret_array = array(); + $fldval=''; + $enclosed = false; +// $fldcount=0; +// $linecount=0; + for($i=0;$i $val) + { + $blocks .= "block_names[{$i}]='{$it}';\n"; + $i++; + } + + $i = 0; + foreach ($import_class_support as $k => $v) + { + $vals .= "db_names[$i] = '{$k}';\n"; + $comments .= "comment_text[$i] = '{$import_class_comment[$k]}';\n"; +// $temp = $import_class_support[$k]; // Array of import types supported + $j = 0; + $m = 1; // Mask bit + foreach ($db_import_blocks as $it => $val) + { + if (in_array($it,$v)) $j = $j + $m; + $m = $m + $m; + } + $texts .= "db_options[{$i}] = {$j};\n"; + $i++; + } + + $text = " + "; + + return $text; +} + + + +?> diff --git a/e107_plugins/import/languages/English_global.php b/e107_plugins/import/languages/English_global.php index dde46d0d5..dd82228fa 100644 --- a/e107_plugins/import/languages/English_global.php +++ b/e107_plugins/import/languages/English_global.php @@ -1,10 +1,10 @@ - \ No newline at end of file diff --git a/e107_plugins/linkwords/linkwords_sql.php b/e107_plugins/linkwords/linkwords_sql.php index d5825ff68..3aa15daea 100644 --- a/e107_plugins/linkwords/linkwords_sql.php +++ b/e107_plugins/linkwords/linkwords_sql.php @@ -1,11 +1,11 @@ -CREATE TABLE linkwords ( -linkword_id int(10) UNSIGNED NOT NULL auto_increment, -linkword_active tinyint(1) unsigned NOT NULL default '0', -linkword_word varchar(100) NOT NULL default '', -linkword_link varchar(250) NOT NULL default '', -linkword_tooltip text NOT NULL, -linkword_tip_id int(10) UNSIGNED NOT NULL Default '0', -linkword_newwindow tinyint(1) unsigned NOT NULL default '1', -linkword_limit int(3) UNSIGNED NOT NULL default '0', -PRIMARY KEY (linkword_id) +CREATE TABLE linkwords ( +linkword_id int(10) UNSIGNED NOT NULL auto_increment, +linkword_active tinyint(1) unsigned NOT NULL default '0', +linkword_word varchar(100) NOT NULL default '', +linkword_link varchar(250) NOT NULL default '', +linkword_tooltip text NOT NULL, +linkword_tip_id int(10) UNSIGNED NOT NULL Default '0', +linkword_newwindow tinyint(1) unsigned NOT NULL default '1', +linkword_limit int(3) UNSIGNED NOT NULL default '0', +PRIMARY KEY (linkword_id) ) ENGINE=MyISAM AUTO_INCREMENT=1; \ No newline at end of file diff --git a/e107_plugins/list_new/languages/English_global.php b/e107_plugins/list_new/languages/English_global.php index e797dc7c6..3d518a493 100644 --- a/e107_plugins/list_new/languages/English_global.php +++ b/e107_plugins/list_new/languages/English_global.php @@ -1,10 +1,10 @@ -addDebug(print_r($logVals, true)); - - - if($_SESSION['stats_log_files'][$count]['complete'] != 1) - { - $_SESSION['stats_log_files'][$count]['complete'] = 1; - // $lg->addSuccess($count."/".$totalFiles."\t".$file." processing", false); - // if($process) - if($lgc->processRawBackupLog($file, true)) - { - - // sleep(3); - $lg->addSuccess($count."/".$totalFiles."\t".$file." processed.", false); - $_SESSION['stats_log_files'][$count]['complete'] = 1; - $_SESSION['stats_log_files_count']++; - } - else - { - $lg->addError($count."/".$totalFiles."\t".$file." failed.", false); - } - } - else - { - $lg->addWarning($count."/".$totalFiles."\t".$file." skipped", false); - $_SESSION['stats_log_files_count']++; - } - - - $totalOutput = round(( $count/ $totalFiles) * 100, 1); - - if($totalOutput > 99.9) - { - echo 100; - if($lgc->collatePageTotalDB()) - { - $lg->addSuccess("Processed All-Time PageTotal", false); - } - else - { - $lg->addError("Failed to Process All-Time PageTotal", false); - } - - $lg->addSuccess("Processing Complete.", false); - - } - else - { - echo $totalOutput; - } - - $lg->toFile('SiteStatsUpgrade','Statistics Update Log', true); - - exit; - -} - -define('LogFlagFile', 'LogFlag.php'); - -e107::includeLan(e_PLUGIN.'log/languages/'.e_LANGUAGE.'.php'); -e107::includeLan(e_PLUGIN.'log/languages/'.e_LANGUAGE.'_admin.php'); - -if(!is_writable(e_LOG)) -{ - //$message = "".ADSTAT_LAN_38.""; - e107::getMessage()->addError(ADSTAT_LAN_28); -} - -e107::css('inline', 'td.last.options { padding-right:20px } '); - - // Needed on Windoze platforms - not an ideal solution! - if (!function_exists('nl_langinfo')) - { - define('MON_1',86400); - define('MON_2',2764800); - define('MON_3',5443200); - define('MON_4',8035200); - define('MON_5',10800000); - define('MON_6',13392000); - define('MON_7',15811200); - define('MON_8',19008000); - define('MON_9',21168000); - define('MON_10',23760000); - define('MON_11',26352000); - define('MON_12',28944000); - - function nl_langinfo($mon) - { - return date('F',$mon); - } - } - - - - - class log_adminArea extends e_admin_dispatcher - { - - protected $modes = array( - - 'main' => array( - 'controller' => 'logstats_ui', - 'path' => null, - 'ui' => 'logstats_form_ui', - 'uipath' => null - ), - - - ); - - - protected $adminMenu = array( - - 'main/prefs' => array('caption'=> LAN_SETTINGS, 'perm' => 'P'), - 'main/list' => array('caption'=> ADSTAT_LAN_48, 'perm' => 'P'), - 'main/export' => array('caption'=> ADSTAT_LAN_36, 'perm' => 'P'), - 'main/datasets' => array('caption'=> ADSTAT_LAN_63, 'perm' => 'P'), - 'main/rempage' => array('caption'=> ADSTAT_LAN_26, 'perm' => 'P'), - 'main/history' => array('caption'=> ADSTAT_LAN_69, 'perm' => 'P'), - 'main/rebuild' => array('caption'=> ADSTAT_LAN_87, 'perm'=> 'P'), - ); - - - - - - protected $adminMenuAliases = array( - 'main/edit' => 'main/list' - ); - - protected $menuTitle = ADSTAT_L3; - } - - - // List of the non-page-based info which is gathered - historically only 'all-time' stats, now we support monthly as well - $stats_list = array('statBrowser'=>ADSTAT_LAN_6,'statOs'=>ADSTAT_LAN_7,'statScreen'=>ADSTAT_LAN_8,'statDomain'=>ADSTAT_LAN_9,'statReferer'=>ADSTAT_LAN_10,'statQuery'=>ADSTAT_LAN_11); - - $separator_list = array(1 => ADSTAT_LAN_57, 2 => ADSTAT_LAN_58); - $separator_char = array(1 => ',', 2 => '|'); - $quote_list = array(1 => ADSTAT_LAN_50, 2 => ADSTAT_LAN_55, 3 => ADSTAT_LAN_56); - $quote_char = array(1 => '', 2 => "'", 3 => '"'); - - - //--------------------------------------------- - // Export data file - //--------------------------------------------- - $export_filter = ''; // can be 'LIKE', 'REGEX', or simple equality - $export_type = $tp->toDB(varset($_POST['export_type'],'page')); // Page data or one of the other bits of info - $export_date = intval(varset($_POST['export_date'],1)); - $export2_date = intval(varset($_POST['export2_date'],3)); - $export_year = intval(varset($_POST['export_year'],date('Y'))); - $export_month = intval(varset($_POST['export_month'],date('m'))); - $export_day = intval(varset($_POST['export_day'],date('j'))); - $export_char = varset($_POST['export_char'], 1); - $export_quote = varset($_POST['export_quote'], 1); - $export_stripurl = varset($_POST['export_stripurl'], 0); - - - - - - - - - class logstats_ui extends e_admin_ui - { - - protected $pluginTitle = ADSTAT_L3; - protected $pluginName = 'log'; - // protected $eventName = 'log-logstats'; // remove comment to enable event triggers in admin. - protected $table = 'logstats'; - protected $pid = 'log_uniqueid'; - protected $perPage = 10; - protected $batchDelete = true; - // protected $batchCopy = true; - // protected $sortField = 'somefield_order'; - // protected $orderStep = 10; - // protected $tabs = array('Tabl 1','Tab 2'); // Use 'tab'=>0 OR 'tab'=>1 in the $fields below to enable. - protected $listQry = "SELECT * FROM `#logstats` WHERE `log_id` = 'pageTotal' OR (`log_id` REGEXP '^[0-9]' AND LENGTH(log_id) > 7 AND LENGTH(log_id) < 11) "; - - // protected $listQry = "SELECT * FROM `#tableName` WHERE field != '' "; // Example Custom Query. LEFT JOINS allowed. Should be without any Order or Limit. - - protected $listOrder = 'CASE log_id WHEN "pageTotal" THEN 9999 ELSE DATE(log_id) END DESC '; - - - protected $fields = array ( 'checkboxes' => array ( 'title' => '', 'type' => null, 'data' => null, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect', ), - 'log_uniqueid' => array ( 'title' => LAN_ID, 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'log_id' => array ( 'title' => LAN_DATE, 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'log_data' => array ( 'title' => ADSTAT_L21, 'type' => 'method', 'data' => 'str', 'width' => '20%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'right', 'thclass' => 'right', ), - 'log_data2' => array ( 'title' => ADSTAT_L22, 'type' => 'method', 'data' => false, 'width' => '20%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'right', 'thclass' => 'right', ), - - 'options' => array ( 'title' => LAN_OPTIONS, 'type' => 'method', 'data' => null, 'width' => '15%', 'thclass' => 'right last', 'class' => 'right last', 'forced' => '1', ), - ); - - protected $fieldpref = array(); - - - // protected $preftabs = array('General', 'Other' ); - protected $prefs = array( - ); - - - public function init() - { - if(!empty($_POST['rebuild'])) - { - require_once(e_PLUGIN.'log/consolidate.php'); - $lgc = new logConsolidate(); - $file = $_POST['rebuild']."_SiteStats.log"; - $lgc->processRawBackupLog($file, true); - } - - if(!empty($_POST['rebuildTotal'])) - { - require_once(e_PLUGIN.'log/consolidate.php'); - $lgc = new logConsolidate(); - - if($lgc->collatePageTotalDB()) - { - e107::getMessage()->addSuccess(LAN_UPDATED); - } - else - { - e107::getMessage()->addError(LAN_UPDATED_FAILED); - } - - } - - // Set drop-down values (if any). - if (isset($_POST['updatesettings'])) - { - $this->prefsPageSubmit(); - } - - if(isset($_POST['remSelP'])) - { - $this->rempagePageSubmit(); // Do the deletions - then redisplay the list of pages - } - - - if(isset($_POST['wipeSubmit'])) - { - $this->wipe(); - } - } - - - /** - * Wipe accumulated stats - */ - private function wipe() - { - $sql = e107::getDb(); - - $logStr = ''; - foreach($_POST['wipe'] as $key => $wipe) - { - switch($key) - { - case "statWipePage": - $sql->update("logstats", "log_data='' WHERE log_id='pageTotal' "); - $sql->update("logstats", "log_data='' WHERE log_id='statTotal' "); - $sql->update("logstats", "log_data='' WHERE log_id='statUnique' "); - break; - - case "statWipeBrowser": - $sql->update("logstats", "log_data='' WHERE log_id='statBrowser' "); - break; - - case "statWipeOs": - $sql->update("logstats", "log_data='' WHERE log_id='statOs' "); - break; - - case "statWipeScreen": - $sql->update("logstats", "log_data='' WHERE log_id='statScreen' "); - break; - - case "statWipeDomain": - $sql->update("logstats", "log_data='' WHERE log_id='statDomain' "); - break; - - case "statWipeRefer": - $sql->update("logstats", "log_data='' WHERE log_id='statReferer' "); - break; - - case "statWipeQuery": - $sql->update("logstats", "log_data='' WHERE log_id='statQuery' "); - break; - - } - - $logStr .= '[!br!]'.$key; - } - - e107::getLog()->add('STAT_01',ADSTAT_LAN_81.$logStr,''); - - e107::getMessage()->addSuccess(LAN_UPDATED); - - } - - private function get_for_delete($keep_year,$keep_month = 1, $filter='*') - { - - $sql = e107::getDb(); - - global $stats_list; - $ret = array(); - // Its tedious, but the filter criteria are sufficiently tricky that its probably best to read all records and decide what can go - if ($sql->select('logstats','log_id')) - { - while ($row = $sql->fetch()) - { - $can_go = FALSE; - $check = FALSE; - $data_type = 'unknown'; - $date_info = $row['log_id']; - if (($temp = strpos($date_info,':')) !== FALSE) - { // its monthly browser stats and similar -// echo "Checking {$date_info}, posn = {$temp} "; - $data_type = substr($date_info,0,$temp); - $date_info = substr($date_info,$temp+1); - $check = TRUE; -// echo "Date string: {$date_info}, data type: {$data_type}
"; - if (isset($stats_list[$data_type])) $data_type = $stats_list[$data_type]; - } - list($poss_year,$poss_month,$poss_day) = explode('-',$date_info.'--',3); - if (!$check) - { - if (is_numeric($poss_year)) - { - $check = TRUE; - if ($poss_day > 0) $data_type = 'daily'; else $data_type = 'monthly'; - } - } - if ($check) - { - if ($keep_year == $poss_year) - { - if (($poss_month > 0) && ($poss_month < $keep_month)) $can_go = TRUE; - } - elseif ($keep_year > $poss_year) $can_go = TRUE; - } - if ($can_go) - { - $ret[$row['log_id']] = $row['log_id']." - ".$data_type; - } - } - } - - return $ret; - - } - - private function data_type_select($name,$value) - { - global $stats_list; - - $ret = "\n"; - return $ret; - } - - - - private function gen_select($prompt,$name,$value) - { - $ret = "
- ".$prompt."
"; - return $ret; - } - - - function datasetsPage() - { - return $this->export('datasets'); - } - - function exportPage() - { - return $this->export('export'); - } - - private function export($action) - { - global $export_type, $export_date, $export2_date, $export_day, $export_month, $export_year, $separator_list, - $export_char, $quote_list, $export_quote, $export_filter; - - $frm = e107::getForm(); - $sql = e107::getDb(); - - $text = "
"; - - if ($action == 'export') - { - $text .= "
"; - } - else - { - $text .= ""; - } - - $text .= " - - - - - "; - - if ($action == 'export') - { - $text .= ""; - } - else - { - $text .= ""; - } - - // Type of output data - page data, browser stats.... - $text .= "'; - // Period selection type for page data - $text .= ""; - - - - $text .= ""; - - - if ($action == 'export') - { - // Separators, quotes - $text .= ""; - - $text .= " - - - "; - } - - - if ($export_filter) - { - if (getperms('0')) $text .= ""; - $sql ->select("logstats", "log_id", "{$export_filter} "); - $text .= ""; - } - - $text .= " -
".ADSTAT_LAN_67."
".ADSTAT_LAN_68."
".ADSTAT_LAN_51."\n".$this->data_type_select('export_type',$export_type).'
".ADSTAT_LAN_41."\n - "; - - // Period selection type for non-page data - $text .= " - "; - - $text .= "
".ADSTAT_LAN_46."\n"; - - - // Now put the various dropdowns - their visibility is controlled by the export_type dropdown - - $text .= "\n   "; - - - $text .= "\n   "; - - $this_year = date("Y"); - $text .= "\n   "; - - $text .= "\n"; - - $text .= "
".ADSTAT_LAN_59."\n - \n    \n
".ADSTAT_LAN_60."".$frm->checkbox('export_stripurl', 1)."".ADSTAT_LAN_61."
".ADSTAT_LAN_65."".$export_filter."
".ADSTAT_LAN_64.""; - while($row = $sql ->fetch()) - { - $text .= $row['log_id']."
"; - } - $text .= "
-
- ".$frm->admin_button('create_export', ($action == 'export' ? LAN_CREATE : ADSTAT_LAN_66), 'update')." -
-
-
"; - - // Set up the date display boxes - $text .= ""; - - return $text; - //$ns->tablerender(ADSTAT_LAN_40, $text); - } - - - - private function rempagePageSubmit() - { - - $ipAddresses = null; - $siteTotal = null; - $siteUnique = null; - - $sql = e107::getDb(); - - $pageInfo = array(); - - $sql->select("logstats", "*", "log_id='pageTotal' "); - $row = $sql ->fetch(); - $pageTotal = unserialize($row['log_data']); - $logfile = e_LOG."logp_".date("z.Y", time()).".php"; - - if(is_readable($logfile)) - { - require($logfile); - } - - foreach($_POST['remcb'] as $page) - { - unset($pageInfo[$page]); - unset($pageTotal[$page]); - } - - $pagetotal = serialize($pageTotal); - - if(!$sql->update("logstats", "log_data='{$pagetotal}' WHERE log_id='pageTotal' ")) - { - $sql->insert("logstats", "0, 'pageTotal', '{$pagetotal}' "); - } - - e107::getLog()->add('STAT_03',ADSTAT_LAN_80."[!br!]".implode("[!br!]",$_POST['remcb']),''); - - $varStart = chr(36); - $quote = chr(34); - - $data = chr(60)."?php\n". chr(47)."* e107 website system: Log file: ".date("z:Y", time())." *". chr(47)."\n\n". - $varStart."ipAddresses = ".$quote.$ipAddresses.$quote.";\n". - $varStart."siteTotal = ".$quote.$siteTotal.$quote.";\n". - $varStart."siteUnique = ".$quote.$siteUnique.$quote.";\n"; - - $loop = FALSE; - $data .= $varStart."pageInfo = array(\n"; - foreach($pageInfo as $info) - { - $page = preg_replace("/(\?.*)|(\_.*)|(\.php)|(\s)|(\')|(\")|(eself)|( )/", "", basename ($info['url'])); - $page = str_replace("\\", "", $page); - $info['url'] = preg_replace("/(\s)|(\')|(\")|(eself)|( )/", "", $info['url']); - $info['url'] = str_replace("\\", "", $info['url']); - $page = trim($page); - if($page && !strstr($page, "cache") && !strstr($page, "file:")) - { - if($loop){ $data .= ",\n"; } - $data .= $quote.$page.$quote." => array('url' => '".$info['url']."', 'ttl' => ".$info['ttl'].", 'unq' => ".$info['unq'].")"; - $loop = 1; - } - } - - $data .= "\n);\n\n?". chr(62); - - if ($handle = fopen($logfile, 'w')) - { - fwrite($handle, $data); - } - fclose($handle); - } - - - - function rempagePage() - { - $sql = e107::getDb(); - $frm = e107::getForm(); - $pageInfo = array(); - $tp = e107::getParser(); - - $logfile = e_LOG."logp_".date("z.Y", time()).".php"; - // $logfile = e_PLUGIN."log/logs/logp_".date("z.Y", time()).".php"; - if(is_readable($logfile)) - { - require($logfile); - } - - $sql ->select("logstats", "*", "log_id='pageTotal' "); - $row = $sql ->fetch(); - $pageTotal = unserialize($row['log_data']); - - - - foreach($pageInfo as $url => $tmpcon) - { - $pageTotal[$url]['url'] = $tmpcon['url']; - $pageTotal[$url]['ttlv'] += $tmpcon['ttl']; - $pageTotal[$url]['unqv'] += $tmpcon['unq']; - } - - - - $text = " -
- - - - - - - - - "; - - foreach($pageTotal as $key => $page) - { - - list($name,$lang) = explode("|",$key); - - $text .= " - - - - - - - - "; - } - - $text .= " -
".ADSTAT_LAN_30." ...".ADSTAT_LAN_86."".ADSTAT_LAN_29."URL
".number_format($page['ttlv'])."{$name}".$tp->text_truncate($page['url'],100)."
-
- ".$frm->admin_button('remSelP', ADSTAT_LAN_31, 'delete')." - - - "; - - return $text; - - // $ns -> tablerender(ADSTAT_LAN_32, $text); - } - - - function rebuildPage() - { - $frm = e107::getForm(); - $mes = e107::getMessage(); - $tp = e107::getParser(); - - $mes->addWarning(ADSTAT_LAN_84); - $text = $frm->open('rebuild'); - - $files = e107::getFile()->get_files(e_LOG."log",'_SiteStats\.log$'); - - // print_a($_SESSION['stats_log_files']); - - $_SESSION['stats_log_files'] = array(); - $_SESSION['stats_log_files_count'] = 0; - - foreach($files as $f) - { - $_SESSION['stats_log_files'][] = array('path'=> $f['fname'], 'complete'=>0); - } - - $_SESSION['stats_log_files_total'] = count($_SESSION['stats_log_files']); - - // $text .= // . " log files have been found. Click the button below to process these files.

"; - $mes->addWarning($tp->lanVars(ADSTAT_LAN_85, $_SESSION['stats_log_files_total'], true)); - - if(!empty($_SESSION['stats_log_files_total'])) - { - $text .= $frm->progressBar('rebuild-progress',0,array("btn-label"=> ADSTAT_LAN_88, 'url'=>e_REQUEST_URI)); - } - - $text .= $frm->close(); - return $text; - - - } - - - - function historyPage() - { - $mes = e107::getMessage(); - $frm = e107::getForm(); - $sql = e107::getDb(); - - $mes->addWarning(ADSTAT_LAN_76); - $text = " - -
- - - - - "; - - $keep_month = varset($_POST['delete_month'],0); - $keep_year = varset($_POST['delete_year'],0); - - if (isset($_POST['delete_history'])) - { - $text .= " - "; - $text .= ""; - } - else - { - if (isset($_POST['actually_delete'])) - { - $delete_list = $this->get_for_delete($keep_year,$keep_month); - $logStr = ''; - // $text .= ""; - $text .= ""; - e107::getLog()->add('STAT_04',ADSTAT_LAN_83.$logStr,''); - } - - $text .= ""; - $text .= ""; - } - - $text .= "
".ADSTAT_LAN_72."".nl_langinfo(constant('MON_'.$keep_month))." ".$keep_year."
- - - ".$frm->admin_button('actually_delete', LAN_CONFDELETE, 'delete')."
".ADSTAT_LAN_74." -
".ADSTAT_LAN_75."".implode("
",$this->get_for_delete($keep_year,$keep_month))."
Data notionally deleted {$keep_month}-{$keep_year}
".ADSTAT_LAN_77.""; - - foreach ($delete_list as $k => $v) - { - $sql->delete('logstats',"log_id='{$k}'"); - $text .= $v."
"; - $logStr .= "[!br!]{$k} => ".$v; - } - - $text .= "
".ADSTAT_LAN_70."\n   "; - $this_year = date("Y"); - - $text .= "\n
- -
- ".$frm->admin_button('delete_history',LAN_DELETE,'delete')." -
- -
"; - - return $text; - // $ns->tablerender(ADSTAT_LAN_69, $mes->render().$text); - } - - - - private function prefsPageSubmit() - { - - $statList = array( // Type = 0 for direct text, 1 for integer - 'statActivate' => 0, - 'statCountAdmin' => 0, - 'statUserclass' => 0, - 'statBrowser' => 1, - 'statOs' => 1, - 'statScreen' => 1, - 'statDomain' => 1, - 'statRefer' => 1, - 'statQuery' => 1, - 'statRecent' => 1, - 'statDisplayNumber' => 0, - 'statPrevMonth' => 1 - ); - $logStr = ''; - - $pref = array(); - - foreach ($statList as $k => $type) - { - switch ($type) - { - case 0 : $pref[$k] = $_POST[$k]; break; - case 1 : $pref[$k] = intval($_POST[$k]); break; - } - $logStr .= "[!br!]{$k} => ".$pref[$k]; - } - - e107::getConfig()->setPref($pref)->save(false,true,true); - - file_put_contents(e_LOG.LogFlagFile, "\n"); // Logging task uses to see if logging enabled - e107::getLog()->add('STAT_02',ADSTAT_LAN_82.$logStr,''); - - - } - - - public function prefsPage() - { - - global $pref; - - $frm = e107::getForm(); - - $text = " -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
".ADSTAT_LAN_4."".$frm->radio_switch('statActivate', $pref['statActivate'])."
".ADSTAT_LAN_18."".r_userclass("statUserclass", $pref['statUserclass'],'off','public, member, admin, classes')."
".ADSTAT_LAN_20."".$frm->radio_switch('statCountAdmin', $pref['statCountAdmin'])."
".ADSTAT_LAN_21."
".ADSTAT_LAN_5." - ".$this->gen_select(ADSTAT_LAN_6, 'statBrowser',$pref['statBrowser']) - .$this->gen_select(ADSTAT_LAN_7, 'statOs',$pref['statOs']) - .$this->gen_select(ADSTAT_LAN_8, 'statScreen',$pref['statScreen']) - .$this->gen_select(ADSTAT_LAN_9, 'statDomain',$pref['statDomain']) - .$this->gen_select(ADSTAT_LAN_10, 'statRefer',$pref['statRefer']) - .$this->gen_select(ADSTAT_LAN_11, 'statQuery',$pref['statQuery']) - ."
".ADSTAT_LAN_19." - ".$frm->radio_switch('statRecent', $pref['statRecent'])."
-
".ADSTAT_LAN_78."".$frm->checkbox('statPrevMonth', 1, varset($pref['statPrevMonth'],0))."".ADSTAT_LAN_79."
".ADSTAT_LAN_12." - ".$frm->checkbox('wipe[statWipePage]', 1, false, array('label'=> ADSTAT_LAN_14 ))." - ".$frm->checkbox('wipe[statWipeBrowser]', 1, false, array('label'=>ADSTAT_LAN_6))." - ".$frm->checkbox('wipe[statWipeOs]', 1, false, array('label'=> ADSTAT_LAN_7 ))." - ".$frm->checkbox('wipe[statWipeScreen]', 1, false, array('label'=> ADSTAT_LAN_8 ))." - ".$frm->checkbox('wipe[statWipeDomain]', 1, false, array('label'=> ADSTAT_LAN_9 ))." - ".$frm->checkbox('wipe[statWipeRefer]', 1, false, array('label'=> ADSTAT_LAN_10 ))." - ".$frm->checkbox('wipe[statWipeQuery]', 1, false, array('label'=> ADSTAT_LAN_11 ))." -
- ".$frm->admin_button('wipeSubmit', LAN_RESET, 'delete')."".ADSTAT_LAN_13." -
".ADSTAT_LAN_26."".$frm->admin_button('openRemPageD', ADSTAT_LAN_28, 'other')."".ADSTAT_LAN_27."
-
- ".$frm->admin_button('updatesettings', LAN_UPDATE, 'update')." -
-
"; - - return $text; - // $ns->tablerender(ADSTAT_LAN_16, $text); - } - - - - - /* - // optional - a custom page. - public function customPage() - { - $text = 'Hello World!'; - return $text; - - } - */ - - } - - - - class logstats_form_ui extends e_admin_form_ui - { - - function log_id($curVal,$mode) - { - switch($mode) - { - case 'read': // List Page - - if($curVal == 'pageTotal') - { - return ADSTAT_LAN_45; // All Time. - } - - return $curVal; - break; - - case 'write': // Edit Page - return ''; - break; - - case 'filter': - case 'batch': - return array(); - break; - } - - } - - - function parseLogData($type) - { - $row = $this->getController()->getListModel()->getData(); - $curVal = $row['log_data']; - - if($row['log_id'] == 'pageTotal') - { - $tmp = unserialize($curVal); - - $ttl = 0; - $unq = 0; - - foreach($tmp as $k=>$v) - { - $ttl += $v['ttlv']; - $unq += $v['unqv']; - } - - if($type == 'total') - { - return number_format($ttl); - } - elseif($type == 'unique') - { - return number_format($unq); - } - - return "
".ADSTAT_L21.": ".number_format($ttl)."
".ADSTAT_L22.": ".number_format($unq)."
Total Pages: ".number_format(count($tmp))."
"; - - - // return print_a($tmp,true); - } - - if(!empty($curVal)) - { - $tmp = explode(chr(1), $curVal, 3); - - if($type == 'total') - { - return number_format($tmp[0]); - } - elseif($type == 'unique') - { - return number_format($tmp[1]); - } - - // return "
".ADSTAT_L21.": ".number_format($tmp[0])."
".ADSTAT_L22.": ".number_format($tmp[1])."
"; - } - - } - - // Total Hits - function log_data($curVal,$mode) - { - - switch($mode) - { - case 'read': // List Page - - return $this->parseLogData('total'); - break; - - case 'write': // Edit Page - // return $this->text('log_data',$curVal, 255, 'size=large'); - break; - - case 'filter': - case 'batch': - return array(); - break; - } - - return null; - } - - - // unique hits - function log_data2($curVal,$mode) - { - - switch($mode) - { - case 'read': // List Page - - return $this->parseLogData('unique'); - break; - - case 'write': // Edit Page - // return $this->text('log_data',$curVal, 255, 'size=large'); - break; - - case 'filter': - case 'batch': - return array(); - break; - } - - return null; - } - - - - function options($curVal,$mode) - { - $row = $this->getController()->getListModel()->getData(); - $date = $row['log_id']; - - if($date == 'pageTotal') - { - return $this->button('rebuildTotal', 1, 'delete', ADSTAT_LAN_89); - } - - - $unix = strtotime($date); - - if(empty($unix)) - { - return null; - } - - $datestamp = date("Y-m-d", $unix); - - $file = e_LOG."log/".$datestamp."_SiteStats.log"; - - if(is_readable($file)) - { - return $this->button('rebuild', $datestamp, 'delete', ADSTAT_LAN_89); - } - else - { - return null; - } - - } - - } - - - new log_adminArea(); - - require_once(e_ADMIN."auth.php"); - e107::getAdminUI()->runPage(); - - require_once(e_ADMIN."footer.php"); - exit; - -/* - -require_once(e_ADMIN.'auth.php'); - -require_once(e_HANDLER.'userclass_class.php'); -$frm = e107::getForm(); -$mes = e107::getMessage(); - -*/ - - -if (e_QUERY) -{ - $sl_qs = explode('.', e_QUERY); -} -$action = varset($sl_qs[0],'config'); -$params = varset($sl_qs[1],''); - - - - -if (isset($_POST['create_export']) && (($action == 'export') || ($action == 'datasets'))) -{ - $first_date = 0; - $last_date = 0; - $date_error = FALSE; - if ($export_type == 'page') - { - switch ($export_date) - { - case '1' : // Single day - $first_date = gmmktime(0,0,0,$export_month,$export_day,$export_year); - $last_date = $first_date+86399; - $export_filter = " `log_id`='".date("Y-m-j",$first_date)."'"; - break; - case '2' : // Daily for a month - $first_date = gmmktime(0,0,0,$export_month,1,$export_year); - $last_date = gmmktime(0,0,0,$export_month+1,1,$export_year) - 1; - $export_filter = " LEFT(`log_id`,8)='".gmstrftime("%Y-%m-",$first_date)."'"; - break; - case '3' : // Monthly for a Year - $first_date = gmmktime(0,0,0,1,1,$export_year); - $last_date = gmmktime(0,0,0,1,1,$export_year+1) - 1; - $export_filter = " LENGTH(`log_id`)=7 AND LEFT(`log_id`,5)='".gmstrftime("%Y-",$first_date)."'"; - break; - case '4' : // Accumulated - case '5' : - $export_filter = "`log_id`='pageTotal'"; - $date_error = 'ignore'; - break; - } - } - else - { // Calculate strings for non-page sources - $prefix_len = 0; - $export_date = $export2_date; - if (isset($stats_list[$export_type])) - { - $prefix_len = strlen($export_type) + 1; - switch ($export2_date) - { - case '3' : // Monthly for a Year - if ($prefix_len > 0) - { - $first_date = gmmktime(0,0,0,1,1,$export_year); - $last_date = gmmktime(0,0,0,1,1,$export_year+1) - 1; - $export_filter = " LENGTH(`log_id`)='".($prefix_len + 7)."' AND LEFT(`log_id`,".($prefix_len + 5).")='".$export_type.":".gmstrftime("%Y-",$first_date)."'"; - } - break; - case '4' : // Accumulated - $export_filter = " `log_id`='".$export_type."'"; - $date_error = 'ignore'; - break; - } - } - else - { - $message = ADSTAT_LAN_54; - } - } - if (($date_error != 'ignore') && (($first_date == 0) || ($last_date == 0) || $date_error)) - { - $message = ADSTAT_LAN_47; - } -} - - - -//--------------------------------------------- -// Remove page entries -//--------------------------------------------- -if(isset($_POST['openRemPageD'])) -{ - $action = 'rempage'; -} - - - - - - - - - - -echo $mes->render() ; - - - - - - -switch ($action) -{ - case 'config' : - - break; // case config - - case 'rempage' : // Remove pages -// rempage(); - break; - - - case 'export' : // Export file - case 'datasets' : - //=========================================================== - // EXPORT DATA - //=========================================================== - - break; // case 'export' - - case 'history' : - //=========================================================== - // DELETE HISTORY - //=========================================================== - - break; // case 'history' - -} - - -require_once(e_ADMIN."footer.php"); - - -function headerjs() -{ - $script_js = "\n"; - return $script_js; -} - - - -//--------------------------------------------- -// Remove page entries - prompt/list -//--------------------------------------------- -function rempage() -{ - -} - - -//--------------------------------------------- -// Remove page entries - action -//--------------------------------------------- - - - - -function admin_config_adminmenu() -{ - if (e_QUERY) - { - $tmp = explode(".", e_QUERY); - $action = $tmp[0]; - } - if (!isset($action) || ($action == "")) $action = "config"; - - $var['config']['text'] = ADSTAT_LAN_35; - $var['config']['link'] = 'admin_config.php'; - - $var['export']['text'] = ADSTAT_LAN_36; - $var['export']['link'] ='admin_config.php?export'; - -// $var['datasets']['text'] = ADSTAT_LAN_63; -// $var['datasets']['link'] ='admin_config.php?datasets'; - - $var['rempage']['text'] = ADSTAT_LAN_26; - $var['rempage']['link'] ='admin_config.php?rempage'; - - $var['history']['text'] = ADSTAT_LAN_69; - $var['history']['link'] ='admin_config.php?history'; - - show_admin_menu(ADSTAT_LAN_39, $action, $var); -} - - -?> +addDebug(print_r($logVals, true)); + + + if($_SESSION['stats_log_files'][$count]['complete'] != 1) + { + $_SESSION['stats_log_files'][$count]['complete'] = 1; + // $lg->addSuccess($count."/".$totalFiles."\t".$file." processing", false); + // if($process) + if($lgc->processRawBackupLog($file, true)) + { + + // sleep(3); + $lg->addSuccess($count."/".$totalFiles."\t".$file." processed.", false); + $_SESSION['stats_log_files'][$count]['complete'] = 1; + $_SESSION['stats_log_files_count']++; + } + else + { + $lg->addError($count."/".$totalFiles."\t".$file." failed.", false); + } + } + else + { + $lg->addWarning($count."/".$totalFiles."\t".$file." skipped", false); + $_SESSION['stats_log_files_count']++; + } + + + $totalOutput = round(( $count/ $totalFiles) * 100, 1); + + if($totalOutput > 99.9) + { + echo 100; + if($lgc->collatePageTotalDB()) + { + $lg->addSuccess("Processed All-Time PageTotal", false); + } + else + { + $lg->addError("Failed to Process All-Time PageTotal", false); + } + + $lg->addSuccess("Processing Complete.", false); + + } + else + { + echo $totalOutput; + } + + $lg->toFile('SiteStatsUpgrade','Statistics Update Log', true); + + exit; + +} + +define('LogFlagFile', 'LogFlag.php'); + +e107::includeLan(e_PLUGIN.'log/languages/'.e_LANGUAGE.'.php'); +e107::includeLan(e_PLUGIN.'log/languages/'.e_LANGUAGE.'_admin.php'); + +if(!is_writable(e_LOG)) +{ + //$message = "".ADSTAT_LAN_38.""; + e107::getMessage()->addError(ADSTAT_LAN_28); +} + +e107::css('inline', 'td.last.options { padding-right:20px } '); + + // Needed on Windoze platforms - not an ideal solution! + if (!function_exists('nl_langinfo')) + { + define('MON_1',86400); + define('MON_2',2764800); + define('MON_3',5443200); + define('MON_4',8035200); + define('MON_5',10800000); + define('MON_6',13392000); + define('MON_7',15811200); + define('MON_8',19008000); + define('MON_9',21168000); + define('MON_10',23760000); + define('MON_11',26352000); + define('MON_12',28944000); + + function nl_langinfo($mon) + { + return date('F',$mon); + } + } + + + + + class log_adminArea extends e_admin_dispatcher + { + + protected $modes = array( + + 'main' => array( + 'controller' => 'logstats_ui', + 'path' => null, + 'ui' => 'logstats_form_ui', + 'uipath' => null + ), + + + ); + + + protected $adminMenu = array( + + 'main/prefs' => array('caption'=> LAN_SETTINGS, 'perm' => 'P'), + 'main/list' => array('caption'=> ADSTAT_LAN_48, 'perm' => 'P'), + 'main/export' => array('caption'=> ADSTAT_LAN_36, 'perm' => 'P'), + 'main/datasets' => array('caption'=> ADSTAT_LAN_63, 'perm' => 'P'), + 'main/rempage' => array('caption'=> ADSTAT_LAN_26, 'perm' => 'P'), + 'main/history' => array('caption'=> ADSTAT_LAN_69, 'perm' => 'P'), + 'main/rebuild' => array('caption'=> ADSTAT_LAN_87, 'perm'=> 'P'), + ); + + + + + + protected $adminMenuAliases = array( + 'main/edit' => 'main/list' + ); + + protected $menuTitle = ADSTAT_L3; + } + + + // List of the non-page-based info which is gathered - historically only 'all-time' stats, now we support monthly as well + $stats_list = array('statBrowser'=>ADSTAT_LAN_6,'statOs'=>ADSTAT_LAN_7,'statScreen'=>ADSTAT_LAN_8,'statDomain'=>ADSTAT_LAN_9,'statReferer'=>ADSTAT_LAN_10,'statQuery'=>ADSTAT_LAN_11); + + $separator_list = array(1 => ADSTAT_LAN_57, 2 => ADSTAT_LAN_58); + $separator_char = array(1 => ',', 2 => '|'); + $quote_list = array(1 => ADSTAT_LAN_50, 2 => ADSTAT_LAN_55, 3 => ADSTAT_LAN_56); + $quote_char = array(1 => '', 2 => "'", 3 => '"'); + + + //--------------------------------------------- + // Export data file + //--------------------------------------------- + $export_filter = ''; // can be 'LIKE', 'REGEX', or simple equality + $export_type = $tp->toDB(varset($_POST['export_type'],'page')); // Page data or one of the other bits of info + $export_date = intval(varset($_POST['export_date'],1)); + $export2_date = intval(varset($_POST['export2_date'],3)); + $export_year = intval(varset($_POST['export_year'],date('Y'))); + $export_month = intval(varset($_POST['export_month'],date('m'))); + $export_day = intval(varset($_POST['export_day'],date('j'))); + $export_char = varset($_POST['export_char'], 1); + $export_quote = varset($_POST['export_quote'], 1); + $export_stripurl = varset($_POST['export_stripurl'], 0); + + + + + + + + + class logstats_ui extends e_admin_ui + { + + protected $pluginTitle = ADSTAT_L3; + protected $pluginName = 'log'; + // protected $eventName = 'log-logstats'; // remove comment to enable event triggers in admin. + protected $table = 'logstats'; + protected $pid = 'log_uniqueid'; + protected $perPage = 10; + protected $batchDelete = true; + // protected $batchCopy = true; + // protected $sortField = 'somefield_order'; + // protected $orderStep = 10; + // protected $tabs = array('Tabl 1','Tab 2'); // Use 'tab'=>0 OR 'tab'=>1 in the $fields below to enable. + protected $listQry = "SELECT * FROM `#logstats` WHERE `log_id` = 'pageTotal' OR (`log_id` REGEXP '^[0-9]' AND LENGTH(log_id) > 7 AND LENGTH(log_id) < 11) "; + + // protected $listQry = "SELECT * FROM `#tableName` WHERE field != '' "; // Example Custom Query. LEFT JOINS allowed. Should be without any Order or Limit. + + protected $listOrder = 'CASE log_id WHEN "pageTotal" THEN 9999 ELSE DATE(log_id) END DESC '; + + + protected $fields = array ( 'checkboxes' => array ( 'title' => '', 'type' => null, 'data' => null, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect', ), + 'log_uniqueid' => array ( 'title' => LAN_ID, 'data' => 'int', 'width' => '5%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'log_id' => array ( 'title' => LAN_DATE, 'type' => 'method', 'data' => 'str', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), + 'log_data' => array ( 'title' => ADSTAT_L21, 'type' => 'method', 'data' => 'str', 'width' => '20%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'right', 'thclass' => 'right', ), + 'log_data2' => array ( 'title' => ADSTAT_L22, 'type' => 'method', 'data' => false, 'width' => '20%', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'right', 'thclass' => 'right', ), + + 'options' => array ( 'title' => LAN_OPTIONS, 'type' => 'method', 'data' => null, 'width' => '15%', 'thclass' => 'right last', 'class' => 'right last', 'forced' => '1', ), + ); + + protected $fieldpref = array(); + + + // protected $preftabs = array('General', 'Other' ); + protected $prefs = array( + ); + + + public function init() + { + if(!empty($_POST['rebuild'])) + { + require_once(e_PLUGIN.'log/consolidate.php'); + $lgc = new logConsolidate(); + $file = $_POST['rebuild']."_SiteStats.log"; + $lgc->processRawBackupLog($file, true); + } + + if(!empty($_POST['rebuildTotal'])) + { + require_once(e_PLUGIN.'log/consolidate.php'); + $lgc = new logConsolidate(); + + if($lgc->collatePageTotalDB()) + { + e107::getMessage()->addSuccess(LAN_UPDATED); + } + else + { + e107::getMessage()->addError(LAN_UPDATED_FAILED); + } + + } + + // Set drop-down values (if any). + if (isset($_POST['updatesettings'])) + { + $this->prefsPageSubmit(); + } + + if(isset($_POST['remSelP'])) + { + $this->rempagePageSubmit(); // Do the deletions - then redisplay the list of pages + } + + + if(isset($_POST['wipeSubmit'])) + { + $this->wipe(); + } + } + + + /** + * Wipe accumulated stats + */ + private function wipe() + { + $sql = e107::getDb(); + + $logStr = ''; + foreach($_POST['wipe'] as $key => $wipe) + { + switch($key) + { + case "statWipePage": + $sql->update("logstats", "log_data='' WHERE log_id='pageTotal' "); + $sql->update("logstats", "log_data='' WHERE log_id='statTotal' "); + $sql->update("logstats", "log_data='' WHERE log_id='statUnique' "); + break; + + case "statWipeBrowser": + $sql->update("logstats", "log_data='' WHERE log_id='statBrowser' "); + break; + + case "statWipeOs": + $sql->update("logstats", "log_data='' WHERE log_id='statOs' "); + break; + + case "statWipeScreen": + $sql->update("logstats", "log_data='' WHERE log_id='statScreen' "); + break; + + case "statWipeDomain": + $sql->update("logstats", "log_data='' WHERE log_id='statDomain' "); + break; + + case "statWipeRefer": + $sql->update("logstats", "log_data='' WHERE log_id='statReferer' "); + break; + + case "statWipeQuery": + $sql->update("logstats", "log_data='' WHERE log_id='statQuery' "); + break; + + } + + $logStr .= '[!br!]'.$key; + } + + e107::getLog()->add('STAT_01',ADSTAT_LAN_81.$logStr,''); + + e107::getMessage()->addSuccess(LAN_UPDATED); + + } + + private function get_for_delete($keep_year,$keep_month = 1, $filter='*') + { + + $sql = e107::getDb(); + + global $stats_list; + $ret = array(); + // Its tedious, but the filter criteria are sufficiently tricky that its probably best to read all records and decide what can go + if ($sql->select('logstats','log_id')) + { + while ($row = $sql->fetch()) + { + $can_go = FALSE; + $check = FALSE; + $data_type = 'unknown'; + $date_info = $row['log_id']; + if (($temp = strpos($date_info,':')) !== FALSE) + { // its monthly browser stats and similar +// echo "Checking {$date_info}, posn = {$temp} "; + $data_type = substr($date_info,0,$temp); + $date_info = substr($date_info,$temp+1); + $check = TRUE; +// echo "Date string: {$date_info}, data type: {$data_type}
"; + if (isset($stats_list[$data_type])) $data_type = $stats_list[$data_type]; + } + list($poss_year,$poss_month,$poss_day) = explode('-',$date_info.'--',3); + if (!$check) + { + if (is_numeric($poss_year)) + { + $check = TRUE; + if ($poss_day > 0) $data_type = 'daily'; else $data_type = 'monthly'; + } + } + if ($check) + { + if ($keep_year == $poss_year) + { + if (($poss_month > 0) && ($poss_month < $keep_month)) $can_go = TRUE; + } + elseif ($keep_year > $poss_year) $can_go = TRUE; + } + if ($can_go) + { + $ret[$row['log_id']] = $row['log_id']." - ".$data_type; + } + } + } + + return $ret; + + } + + private function data_type_select($name,$value) + { + global $stats_list; + + $ret = "\n"; + return $ret; + } + + + + private function gen_select($prompt,$name,$value) + { + $ret = "
+ ".$prompt."
"; + return $ret; + } + + + function datasetsPage() + { + return $this->export('datasets'); + } + + function exportPage() + { + return $this->export('export'); + } + + private function export($action) + { + global $export_type, $export_date, $export2_date, $export_day, $export_month, $export_year, $separator_list, + $export_char, $quote_list, $export_quote, $export_filter; + + $frm = e107::getForm(); + $sql = e107::getDb(); + + $text = "
"; + + if ($action == 'export') + { + $text .= "
"; + } + else + { + $text .= ""; + } + + $text .= " + + + + + "; + + if ($action == 'export') + { + $text .= ""; + } + else + { + $text .= ""; + } + + // Type of output data - page data, browser stats.... + $text .= "'; + // Period selection type for page data + $text .= ""; + + + + $text .= ""; + + + if ($action == 'export') + { + // Separators, quotes + $text .= ""; + + $text .= " + + + "; + } + + + if ($export_filter) + { + if (getperms('0')) $text .= ""; + $sql ->select("logstats", "log_id", "{$export_filter} "); + $text .= ""; + } + + $text .= " +
".ADSTAT_LAN_67."
".ADSTAT_LAN_68."
".ADSTAT_LAN_51."\n".$this->data_type_select('export_type',$export_type).'
".ADSTAT_LAN_41."\n + "; + + // Period selection type for non-page data + $text .= " + "; + + $text .= "
".ADSTAT_LAN_46."\n"; + + + // Now put the various dropdowns - their visibility is controlled by the export_type dropdown + + $text .= "\n   "; + + + $text .= "\n   "; + + $this_year = date("Y"); + $text .= "\n   "; + + $text .= "\n"; + + $text .= "
".ADSTAT_LAN_59."\n + \n    \n
".ADSTAT_LAN_60."".$frm->checkbox('export_stripurl', 1)."".ADSTAT_LAN_61."
".ADSTAT_LAN_65."".$export_filter."
".ADSTAT_LAN_64.""; + while($row = $sql ->fetch()) + { + $text .= $row['log_id']."
"; + } + $text .= "
+
+ ".$frm->admin_button('create_export', ($action == 'export' ? LAN_CREATE : ADSTAT_LAN_66), 'update')." +
+
+
"; + + // Set up the date display boxes + $text .= ""; + + return $text; + //$ns->tablerender(ADSTAT_LAN_40, $text); + } + + + + private function rempagePageSubmit() + { + + $ipAddresses = null; + $siteTotal = null; + $siteUnique = null; + + $sql = e107::getDb(); + + $pageInfo = array(); + + $sql->select("logstats", "*", "log_id='pageTotal' "); + $row = $sql ->fetch(); + $pageTotal = unserialize($row['log_data']); + $logfile = e_LOG."logp_".date("z.Y", time()).".php"; + + if(is_readable($logfile)) + { + require($logfile); + } + + foreach($_POST['remcb'] as $page) + { + unset($pageInfo[$page]); + unset($pageTotal[$page]); + } + + $pagetotal = serialize($pageTotal); + + if(!$sql->update("logstats", "log_data='{$pagetotal}' WHERE log_id='pageTotal' ")) + { + $sql->insert("logstats", "0, 'pageTotal', '{$pagetotal}' "); + } + + e107::getLog()->add('STAT_03',ADSTAT_LAN_80."[!br!]".implode("[!br!]",$_POST['remcb']),''); + + $varStart = chr(36); + $quote = chr(34); + + $data = chr(60)."?php\n". chr(47)."* e107 website system: Log file: ".date("z:Y", time())." *". chr(47)."\n\n". + $varStart."ipAddresses = ".$quote.$ipAddresses.$quote.";\n". + $varStart."siteTotal = ".$quote.$siteTotal.$quote.";\n". + $varStart."siteUnique = ".$quote.$siteUnique.$quote.";\n"; + + $loop = FALSE; + $data .= $varStart."pageInfo = array(\n"; + foreach($pageInfo as $info) + { + $page = preg_replace("/(\?.*)|(\_.*)|(\.php)|(\s)|(\')|(\")|(eself)|( )/", "", basename ($info['url'])); + $page = str_replace("\\", "", $page); + $info['url'] = preg_replace("/(\s)|(\')|(\")|(eself)|( )/", "", $info['url']); + $info['url'] = str_replace("\\", "", $info['url']); + $page = trim($page); + if($page && !strstr($page, "cache") && !strstr($page, "file:")) + { + if($loop){ $data .= ",\n"; } + $data .= $quote.$page.$quote." => array('url' => '".$info['url']."', 'ttl' => ".$info['ttl'].", 'unq' => ".$info['unq'].")"; + $loop = 1; + } + } + + $data .= "\n);\n\n?". chr(62); + + if ($handle = fopen($logfile, 'w')) + { + fwrite($handle, $data); + } + fclose($handle); + } + + + + function rempagePage() + { + $sql = e107::getDb(); + $frm = e107::getForm(); + $pageInfo = array(); + $tp = e107::getParser(); + + $logfile = e_LOG."logp_".date("z.Y", time()).".php"; + // $logfile = e_PLUGIN."log/logs/logp_".date("z.Y", time()).".php"; + if(is_readable($logfile)) + { + require($logfile); + } + + $sql ->select("logstats", "*", "log_id='pageTotal' "); + $row = $sql ->fetch(); + $pageTotal = unserialize($row['log_data']); + + + + foreach($pageInfo as $url => $tmpcon) + { + $pageTotal[$url]['url'] = $tmpcon['url']; + $pageTotal[$url]['ttlv'] += $tmpcon['ttl']; + $pageTotal[$url]['unqv'] += $tmpcon['unq']; + } + + + + $text = " +
+ + + + + + + + + "; + + foreach($pageTotal as $key => $page) + { + + list($name,$lang) = explode("|",$key); + + $text .= " + + + + + + + + "; + } + + $text .= " +
".ADSTAT_LAN_30." ...".ADSTAT_LAN_86."".ADSTAT_LAN_29."URL
".number_format($page['ttlv'])."{$name}".$tp->text_truncate($page['url'],100)."
+
+ ".$frm->admin_button('remSelP', ADSTAT_LAN_31, 'delete')." + + + "; + + return $text; + + // $ns -> tablerender(ADSTAT_LAN_32, $text); + } + + + function rebuildPage() + { + $frm = e107::getForm(); + $mes = e107::getMessage(); + $tp = e107::getParser(); + + $mes->addWarning(ADSTAT_LAN_84); + $text = $frm->open('rebuild'); + + $files = e107::getFile()->get_files(e_LOG."log",'_SiteStats\.log$'); + + // print_a($_SESSION['stats_log_files']); + + $_SESSION['stats_log_files'] = array(); + $_SESSION['stats_log_files_count'] = 0; + + foreach($files as $f) + { + $_SESSION['stats_log_files'][] = array('path'=> $f['fname'], 'complete'=>0); + } + + $_SESSION['stats_log_files_total'] = count($_SESSION['stats_log_files']); + + // $text .= // . " log files have been found. Click the button below to process these files.

"; + $mes->addWarning($tp->lanVars(ADSTAT_LAN_85, $_SESSION['stats_log_files_total'], true)); + + if(!empty($_SESSION['stats_log_files_total'])) + { + $text .= $frm->progressBar('rebuild-progress',0,array("btn-label"=> ADSTAT_LAN_88, 'url'=>e_REQUEST_URI)); + } + + $text .= $frm->close(); + return $text; + + + } + + + + function historyPage() + { + $mes = e107::getMessage(); + $frm = e107::getForm(); + $sql = e107::getDb(); + + $mes->addWarning(ADSTAT_LAN_76); + $text = " + +
+ + + + + "; + + $keep_month = varset($_POST['delete_month'],0); + $keep_year = varset($_POST['delete_year'],0); + + if (isset($_POST['delete_history'])) + { + $text .= " + "; + $text .= ""; + } + else + { + if (isset($_POST['actually_delete'])) + { + $delete_list = $this->get_for_delete($keep_year,$keep_month); + $logStr = ''; + // $text .= ""; + $text .= ""; + e107::getLog()->add('STAT_04',ADSTAT_LAN_83.$logStr,''); + } + + $text .= ""; + $text .= ""; + } + + $text .= "
".ADSTAT_LAN_72."".nl_langinfo(constant('MON_'.$keep_month))." ".$keep_year."
+ + + ".$frm->admin_button('actually_delete', LAN_CONFDELETE, 'delete')."
".ADSTAT_LAN_74." +
".ADSTAT_LAN_75."".implode("
",$this->get_for_delete($keep_year,$keep_month))."
Data notionally deleted {$keep_month}-{$keep_year}
".ADSTAT_LAN_77.""; + + foreach ($delete_list as $k => $v) + { + $sql->delete('logstats',"log_id='{$k}'"); + $text .= $v."
"; + $logStr .= "[!br!]{$k} => ".$v; + } + + $text .= "
".ADSTAT_LAN_70."\n   "; + $this_year = date("Y"); + + $text .= "\n
+ +
+ ".$frm->admin_button('delete_history',LAN_DELETE,'delete')." +
+ +
"; + + return $text; + // $ns->tablerender(ADSTAT_LAN_69, $mes->render().$text); + } + + + + private function prefsPageSubmit() + { + + $statList = array( // Type = 0 for direct text, 1 for integer + 'statActivate' => 0, + 'statCountAdmin' => 0, + 'statUserclass' => 0, + 'statBrowser' => 1, + 'statOs' => 1, + 'statScreen' => 1, + 'statDomain' => 1, + 'statRefer' => 1, + 'statQuery' => 1, + 'statRecent' => 1, + 'statDisplayNumber' => 0, + 'statPrevMonth' => 1 + ); + $logStr = ''; + + $pref = array(); + + foreach ($statList as $k => $type) + { + switch ($type) + { + case 0 : $pref[$k] = $_POST[$k]; break; + case 1 : $pref[$k] = intval($_POST[$k]); break; + } + $logStr .= "[!br!]{$k} => ".$pref[$k]; + } + + e107::getConfig()->setPref($pref)->save(false,true,true); + + file_put_contents(e_LOG.LogFlagFile, "\n"); // Logging task uses to see if logging enabled + e107::getLog()->add('STAT_02',ADSTAT_LAN_82.$logStr,''); + + + } + + + public function prefsPage() + { + + global $pref; + + $frm = e107::getForm(); + + $text = " +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
".ADSTAT_LAN_4."".$frm->radio_switch('statActivate', $pref['statActivate'])."
".ADSTAT_LAN_18."".r_userclass("statUserclass", $pref['statUserclass'],'off','public, member, admin, classes')."
".ADSTAT_LAN_20."".$frm->radio_switch('statCountAdmin', $pref['statCountAdmin'])."
".ADSTAT_LAN_21."
".ADSTAT_LAN_5." + ".$this->gen_select(ADSTAT_LAN_6, 'statBrowser',$pref['statBrowser']) + .$this->gen_select(ADSTAT_LAN_7, 'statOs',$pref['statOs']) + .$this->gen_select(ADSTAT_LAN_8, 'statScreen',$pref['statScreen']) + .$this->gen_select(ADSTAT_LAN_9, 'statDomain',$pref['statDomain']) + .$this->gen_select(ADSTAT_LAN_10, 'statRefer',$pref['statRefer']) + .$this->gen_select(ADSTAT_LAN_11, 'statQuery',$pref['statQuery']) + ."
".ADSTAT_LAN_19." + ".$frm->radio_switch('statRecent', $pref['statRecent'])."
+
".ADSTAT_LAN_78."".$frm->checkbox('statPrevMonth', 1, varset($pref['statPrevMonth'],0))."".ADSTAT_LAN_79."
".ADSTAT_LAN_12." + ".$frm->checkbox('wipe[statWipePage]', 1, false, array('label'=> ADSTAT_LAN_14 ))." + ".$frm->checkbox('wipe[statWipeBrowser]', 1, false, array('label'=>ADSTAT_LAN_6))." + ".$frm->checkbox('wipe[statWipeOs]', 1, false, array('label'=> ADSTAT_LAN_7 ))." + ".$frm->checkbox('wipe[statWipeScreen]', 1, false, array('label'=> ADSTAT_LAN_8 ))." + ".$frm->checkbox('wipe[statWipeDomain]', 1, false, array('label'=> ADSTAT_LAN_9 ))." + ".$frm->checkbox('wipe[statWipeRefer]', 1, false, array('label'=> ADSTAT_LAN_10 ))." + ".$frm->checkbox('wipe[statWipeQuery]', 1, false, array('label'=> ADSTAT_LAN_11 ))." +
+ ".$frm->admin_button('wipeSubmit', LAN_RESET, 'delete')."".ADSTAT_LAN_13." +
".ADSTAT_LAN_26."".$frm->admin_button('openRemPageD', ADSTAT_LAN_28, 'other')."".ADSTAT_LAN_27."
+
+ ".$frm->admin_button('updatesettings', LAN_UPDATE, 'update')." +
+
"; + + return $text; + // $ns->tablerender(ADSTAT_LAN_16, $text); + } + + + + + /* + // optional - a custom page. + public function customPage() + { + $text = 'Hello World!'; + return $text; + + } + */ + + } + + + + class logstats_form_ui extends e_admin_form_ui + { + + function log_id($curVal,$mode) + { + switch($mode) + { + case 'read': // List Page + + if($curVal == 'pageTotal') + { + return ADSTAT_LAN_45; // All Time. + } + + return $curVal; + break; + + case 'write': // Edit Page + return ''; + break; + + case 'filter': + case 'batch': + return array(); + break; + } + + } + + + function parseLogData($type) + { + $row = $this->getController()->getListModel()->getData(); + $curVal = $row['log_data']; + + if($row['log_id'] == 'pageTotal') + { + $tmp = unserialize($curVal); + + $ttl = 0; + $unq = 0; + + foreach($tmp as $k=>$v) + { + $ttl += $v['ttlv']; + $unq += $v['unqv']; + } + + if($type == 'total') + { + return number_format($ttl); + } + elseif($type == 'unique') + { + return number_format($unq); + } + + return "
".ADSTAT_L21.": ".number_format($ttl)."
".ADSTAT_L22.": ".number_format($unq)."
Total Pages: ".number_format(count($tmp))."
"; + + + // return print_a($tmp,true); + } + + if(!empty($curVal)) + { + $tmp = explode(chr(1), $curVal, 3); + + if($type == 'total') + { + return number_format($tmp[0]); + } + elseif($type == 'unique') + { + return number_format($tmp[1]); + } + + // return "
".ADSTAT_L21.": ".number_format($tmp[0])."
".ADSTAT_L22.": ".number_format($tmp[1])."
"; + } + + } + + // Total Hits + function log_data($curVal,$mode) + { + + switch($mode) + { + case 'read': // List Page + + return $this->parseLogData('total'); + break; + + case 'write': // Edit Page + // return $this->text('log_data',$curVal, 255, 'size=large'); + break; + + case 'filter': + case 'batch': + return array(); + break; + } + + return null; + } + + + // unique hits + function log_data2($curVal,$mode) + { + + switch($mode) + { + case 'read': // List Page + + return $this->parseLogData('unique'); + break; + + case 'write': // Edit Page + // return $this->text('log_data',$curVal, 255, 'size=large'); + break; + + case 'filter': + case 'batch': + return array(); + break; + } + + return null; + } + + + + function options($curVal,$mode) + { + $row = $this->getController()->getListModel()->getData(); + $date = $row['log_id']; + + if($date == 'pageTotal') + { + return $this->button('rebuildTotal', 1, 'delete', ADSTAT_LAN_89); + } + + + $unix = strtotime($date); + + if(empty($unix)) + { + return null; + } + + $datestamp = date("Y-m-d", $unix); + + $file = e_LOG."log/".$datestamp."_SiteStats.log"; + + if(is_readable($file)) + { + return $this->button('rebuild', $datestamp, 'delete', ADSTAT_LAN_89); + } + else + { + return null; + } + + } + + } + + + new log_adminArea(); + + require_once(e_ADMIN."auth.php"); + e107::getAdminUI()->runPage(); + + require_once(e_ADMIN."footer.php"); + exit; + +/* + +require_once(e_ADMIN.'auth.php'); + +require_once(e_HANDLER.'userclass_class.php'); +$frm = e107::getForm(); +$mes = e107::getMessage(); + +*/ + + +if (e_QUERY) +{ + $sl_qs = explode('.', e_QUERY); +} +$action = varset($sl_qs[0],'config'); +$params = varset($sl_qs[1],''); + + + + +if (isset($_POST['create_export']) && (($action == 'export') || ($action == 'datasets'))) +{ + $first_date = 0; + $last_date = 0; + $date_error = FALSE; + if ($export_type == 'page') + { + switch ($export_date) + { + case '1' : // Single day + $first_date = gmmktime(0,0,0,$export_month,$export_day,$export_year); + $last_date = $first_date+86399; + $export_filter = " `log_id`='".date("Y-m-j",$first_date)."'"; + break; + case '2' : // Daily for a month + $first_date = gmmktime(0,0,0,$export_month,1,$export_year); + $last_date = gmmktime(0,0,0,$export_month+1,1,$export_year) - 1; + $export_filter = " LEFT(`log_id`,8)='".gmstrftime("%Y-%m-",$first_date)."'"; + break; + case '3' : // Monthly for a Year + $first_date = gmmktime(0,0,0,1,1,$export_year); + $last_date = gmmktime(0,0,0,1,1,$export_year+1) - 1; + $export_filter = " LENGTH(`log_id`)=7 AND LEFT(`log_id`,5)='".gmstrftime("%Y-",$first_date)."'"; + break; + case '4' : // Accumulated + case '5' : + $export_filter = "`log_id`='pageTotal'"; + $date_error = 'ignore'; + break; + } + } + else + { // Calculate strings for non-page sources + $prefix_len = 0; + $export_date = $export2_date; + if (isset($stats_list[$export_type])) + { + $prefix_len = strlen($export_type) + 1; + switch ($export2_date) + { + case '3' : // Monthly for a Year + if ($prefix_len > 0) + { + $first_date = gmmktime(0,0,0,1,1,$export_year); + $last_date = gmmktime(0,0,0,1,1,$export_year+1) - 1; + $export_filter = " LENGTH(`log_id`)='".($prefix_len + 7)."' AND LEFT(`log_id`,".($prefix_len + 5).")='".$export_type.":".gmstrftime("%Y-",$first_date)."'"; + } + break; + case '4' : // Accumulated + $export_filter = " `log_id`='".$export_type."'"; + $date_error = 'ignore'; + break; + } + } + else + { + $message = ADSTAT_LAN_54; + } + } + if (($date_error != 'ignore') && (($first_date == 0) || ($last_date == 0) || $date_error)) + { + $message = ADSTAT_LAN_47; + } +} + + + +//--------------------------------------------- +// Remove page entries +//--------------------------------------------- +if(isset($_POST['openRemPageD'])) +{ + $action = 'rempage'; +} + + + + + + + + + + +echo $mes->render() ; + + + + + + +switch ($action) +{ + case 'config' : + + break; // case config + + case 'rempage' : // Remove pages +// rempage(); + break; + + + case 'export' : // Export file + case 'datasets' : + //=========================================================== + // EXPORT DATA + //=========================================================== + + break; // case 'export' + + case 'history' : + //=========================================================== + // DELETE HISTORY + //=========================================================== + + break; // case 'history' + +} + + +require_once(e_ADMIN."footer.php"); + + +function headerjs() +{ + $script_js = "\n"; + return $script_js; +} + + + +//--------------------------------------------- +// Remove page entries - prompt/list +//--------------------------------------------- +function rempage() +{ + +} + + +//--------------------------------------------- +// Remove page entries - action +//--------------------------------------------- + + + + +function admin_config_adminmenu() +{ + if (e_QUERY) + { + $tmp = explode(".", e_QUERY); + $action = $tmp[0]; + } + if (!isset($action) || ($action == "")) $action = "config"; + + $var['config']['text'] = ADSTAT_LAN_35; + $var['config']['link'] = 'admin_config.php'; + + $var['export']['text'] = ADSTAT_LAN_36; + $var['export']['link'] ='admin_config.php?export'; + +// $var['datasets']['text'] = ADSTAT_LAN_63; +// $var['datasets']['link'] ='admin_config.php?datasets'; + + $var['rempage']['text'] = ADSTAT_LAN_26; + $var['rempage']['link'] ='admin_config.php?rempage'; + + $var['history']['text'] = ADSTAT_LAN_69; + $var['history']['link'] ='admin_config.php?history'; + + show_admin_menu(ADSTAT_LAN_39, $action, $var); +} + + +?> diff --git a/e107_plugins/log/e_meta.php b/e107_plugins/log/e_meta.php index 342531621..9cadd05d3 100644 --- a/e107_plugins/log/e_meta.php +++ b/e107_plugins/log/e_meta.php @@ -1,106 +1,106 @@ -run(); - - $err_flag = ''; - if (defined('ERR_PAGE_ACTIVE')) - { // We've got an error - set a flag to log it - $err_flag = "&err_direct=".ERR_PAGE_ACTIVE; - if (is_numeric(e_QUERY)) $err_flag .= '/'.substr(e_QUERY,0,10); // This should pick up the error code - and limit numeric length to upset the malicious - $err_flag .= "&err_referer=".$_SERVER['HTTP_REFERER']; - } - - } - - if(USER_AREA) - { - $logJS = " - - $(function() { - - function rstr2b64(input) - { - var b64pad = \"=\"; /* base-64 pad character. \"=\" for strict RFC compliance */ - var tab = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"; - var output = \"\"; - var len = input.length; - for(var i = 0; i < len; i += 3) - { - var triplet = (input.charCodeAt(i) << 16) - | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) - | (i + 2 < len ? input.charCodeAt(i+2) : 0); - for(var j = 0; j < 4; j++) - { - if(i * 8 + j * 6 > input.length * 8) output += b64pad; - else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); - } - } - return output; - } - - - - - - var ref =\"\"+escape(top.document.referrer); - var eeself = escape(window.location.href); - - var colord = window.screen.colorDepth; - var res = window.screen.width + \"x\" + window.screen.height; - var logString = 'referer=' + ref + '&colour=' + colord + '&eself=' + eeself + '&res=' + res + '".$err_flag."'; - logString = rstr2b64(logString); - - var url = '".SITEURLBASE.e_PLUGIN_ABS."log/log.php'; - var dataText = 'lv='+logString; - - $.ajax({ - type: 'get', - url: url, - data: {'lv' :logString}, - success: function(e) { - if(e) - { - // alert(e); - } - } - }); - }); - "; - - - - - e107::js('footer-inline', $logJS, 'jquery'); - } -} - - +run(); + + $err_flag = ''; + if (defined('ERR_PAGE_ACTIVE')) + { // We've got an error - set a flag to log it + $err_flag = "&err_direct=".ERR_PAGE_ACTIVE; + if (is_numeric(e_QUERY)) $err_flag .= '/'.substr(e_QUERY,0,10); // This should pick up the error code - and limit numeric length to upset the malicious + $err_flag .= "&err_referer=".$_SERVER['HTTP_REFERER']; + } + + } + + if(USER_AREA) + { + $logJS = " + + $(function() { + + function rstr2b64(input) + { + var b64pad = \"=\"; /* base-64 pad character. \"=\" for strict RFC compliance */ + var tab = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"; + var output = \"\"; + var len = input.length; + for(var i = 0; i < len; i += 3) + { + var triplet = (input.charCodeAt(i) << 16) + | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) + | (i + 2 < len ? input.charCodeAt(i+2) : 0); + for(var j = 0; j < 4; j++) + { + if(i * 8 + j * 6 > input.length * 8) output += b64pad; + else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); + } + } + return output; + } + + + + + + var ref =\"\"+escape(top.document.referrer); + var eeself = escape(window.location.href); + + var colord = window.screen.colorDepth; + var res = window.screen.width + \"x\" + window.screen.height; + var logString = 'referer=' + ref + '&colour=' + colord + '&eself=' + eeself + '&res=' + res + '".$err_flag."'; + logString = rstr2b64(logString); + + var url = '".SITEURLBASE.e_PLUGIN_ABS."log/log.php'; + var dataText = 'lv='+logString; + + $.ajax({ + type: 'get', + url: url, + data: {'lv' :logString}, + success: function(e) { + if(e) + { + // alert(e); + } + } + }); + }); + "; + + + + + e107::js('footer-inline', $logJS, 'jquery'); + } +} + + ?> \ No newline at end of file diff --git a/e107_plugins/log/log.php b/e107_plugins/log/log.php index cca58db31..b2943e082 100644 --- a/e107_plugins/log/log.php +++ b/e107_plugins/log/log.php @@ -1,311 +1,311 @@ -' );)"; - referer= ref - color= colord - eself= eself - res= res - err_direct - optional error flag - err_referer - referrer if came via error page - qry = 1 to log query part as well - -// Normally the file is 'silent' - if any errors occur, any error message appears in the page header. -*/ -//error_reporting(0); -// error_reporting(E_ALL); -define('e_MINIMAL',true); -require_once("../../class2.php"); // More secure to include it. -header('Cache-Control: no-cache, must-revalidate'); // See if this discourages browser caching -header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past - -define('LOGSTATS_DEBUG', false); - -// @example url: e107_plugins/log/log.php?lv=cmVmZXJlcj1odHRwJTNBLy9sb2NhbGhvc3QlM0E4MDgwL2UxMDdfMi4wL3N0YXRzJmNvbG91cj0yNCZlc2VsZj1odHRwJTNBLy9sb2NhbGhvc3QlM0E4MDgwL2UxMDdfMi4wL2UxMDdfcGx1Z2lucy9sb2cvc3RhdHMucGhwJTNGMiZyZXM9MTkyMHgxMjAw - -if(LOGSTATS_DEBUG === true) -{ - echo "Debug is Active"; -} - -if (!vartrue($pref['statActivate'])) -{ - if(LOGSTATS_DEBUG === true) - { - echo "Stats log is inactive"; - } - - exit(); -} - - - -//print_r(base64_decode($_GET['lv'])); -define('LOGSTATS_INIT', true); - -// Array of page names which should have individual query values recorded. -// The top level array index is the page name. -// If the top level value is an array, it must be an array of query string beginnings to match. -$pageUnique = array('page' => 1, 'content' => array('content')); - -//$logVals = urldecode(base64_decode($_SERVER['QUERY_STRING'])); -//$logVals = urldecode(base64_decode($_GET['lv'])); - - -// --------------- Reworked for v2.x ------------------------ - - -$logVals = base64_decode($_GET['lv']); -$logVals = filter_var($logVals, FILTER_SANITIZE_URL); - -$logVals .= "&ip=".USERIP; -$logVals .= "&iphost=". @gethostbyaddr(USERIP); -$logVals .= "&lan=".e_LAN; -$logVals .= "&agent=".filter_var($_SERVER['HTTP_USER_AGENT'],FILTER_SANITIZE_STRING); - -parse_str($logVals, $vals); - -$vals['referer'] = urldecode($vals['referer']); -$vals['eself'] = urldecode($vals['eself']); - -if(empty($_SESSION['log_userLoggedPages']) || !in_array($vals['eself'],$_SESSION['log_userLoggedPages'])) -{ - $_SESSION['log_userLoggedPages'][] = $vals['eself']; - $logVals .= "&unique=1"; -} -else -{ - $logVals .= "&unique=0"; -} - - -$logVals = str_replace('%3A',':',$logVals); // make the URLs a bit cleaner, while keeping any urlqueries encoded. - -$lg = e107::getAdminLog(); -$lg->addDebug(print_r($logVals, true)); -$lg->toFile('SiteStats','Statistics Log', true); - -e107::getEvent()->trigger('user_log_stats',$vals); - - -// ------------------------------------ --------------------- - -// We MUST have a timezone set in PHP >= 5.3. This should work for PHP >= 5.1: -// @todo may be able to remove this check once minimum PHP version finalised -if (function_exists('date_default_timezone_get')) -{ - date_default_timezone_set(@date_default_timezone_get()); // Just set a default - it should default to UTC if no timezone set -} - - -//$logfp = fopen(e_LOG.'rcvstring.txt', 'a+'); fwrite($logfp, $logVals."\n"); fclose($logfp); -//$logfp = fopen(e_LOG.'rcvstring.txt', 'a+'); fwrite($logfp, print_r($vals, TRUE)."\n"); fclose($logfp); - -$colour = strip_tags((isset($vals['colour']) ? $vals['colour'] : '')); -$res = strip_tags((isset($vals['res']) ? $vals['res'] : '')); -$self = strip_tags((isset($vals['eself']) ? $vals['eself'] : '')); -$ref = addslashes(strip_tags((isset($vals['referer']) ? $vals['referer'] : ''))); -$logQry = isset($vals['qry']) && $vals['qry']; -$date = date('z.Y', time()); -$logPfile = e_LOG.'logp_'.$date.'.php'; - -//$logString = "Colour: {$colour} Res: {$res} Self: {$self} Referrer: {$ref} ErrCode: {$vals['err_direct']}\n"; -//$logfp = fopen(e_LOG.'rcvstring.txt', 'a+'); fwrite($logfp, $logString); fclose($logfp); - - -// vet resolution and colour depth some more - avoid dud values -if ($res && preg_match("#.*?((\d+)\w+?(\d+))#", $res, $match)) -{ - $res = $match[2].'x'.$match[3]; -} -else -{ - $res = '??'; // Can't decode resolution -} - -if ($colour && preg_match("#.*?(\d+)#",$colour,$match)) -{ - $colour = intval($match[1]); -} -else -{ - $colour='??'; -} - - -if ($err_code = strip_tags((isset($vals['err_direct']) ? $vals['err_direct'] : ''))) -{ - $ref = addslashes(strip_tags(isset($vals['err_referer']) ? $vals['err_referer'] : '')); -// Uncomment the next two lines to create a separate CSV format log of invalid accesses - error code, entered URL, referrer -// $log_string = $err_code.",".$self.",".$ref; -// $logfp = fopen(e_LOG."errpages.csv", 'a+'); fwrite($logfp, $log_string."\n\r"); fclose($logfp); - $err_code .= ':'; -} - -if(strstr($ref, 'admin')) -{ - $ref = FALSE; -} - -$screenstats = $res.'@'.$colour; -$agent = $_SERVER['HTTP_USER_AGENT']; -$ip = e107::getIPHandler()->ipDecode(USERIP); - -$oldref = $ref; // backup for search string being stripped off for referer -if($ref && !strstr($ref, $_SERVER['HTTP_HOST'])) -{ - if(preg_match("#http://(.*?)($|/)#is", $ref, $match)) - { - $ref = $match[0]; - } -} - - -$pageDisallow = "cache|file|eself|admin"; -$tagRemove = "(\\\)|(\s)|(\')|(\")|(eself)|( )|(\.php)|(\.html)"; -$tagRemove2 = "(\\\)|(\s)|(\')|(\")|(eself)|( )"; - -/* -function logGetPageKey($url,$logQry=false,$err_code='') -{ - global $pageDisallow, $tagRemove; - - preg_match("#/(.*?)(\?|$)(.*)#si", $url, $match); - $match[1] = isset($match[1]) ? $match[1] : ''; - $pageName = substr($match[1], (strrpos($match[1], "/")+1)); - - $pageName = preg_replace("/".$tagRemove."/si", "", $pageName); - if($pageName == "") - { - return "index"; - } - - if(preg_match("/".$pageDisallow."/i", $pageName)) - { - return false; - } - - if ($logQry) - { - $pageName .= '+'.$match[3]; // All queries match - } - - $pageName = $err_code.$pageName; // Add the error code at the beginning, so its treated uniquely - - - return $pageName; -}*/ - -require_once(e_PLUGIN."log/consolidate.php"); -$lgc = new logConsolidate; - - -if(!$pageName = $lgc->getPageKey($self,false,$err_code,e_LAN)) -{ - if(LOGSTATS_DEBUG == true) - { - echo 'pageName was empty'; - } - return; -} - -if(LOGSTATS_DEBUG == true) -{ - echo "
File: ".$logPfile; -} - -//$logfp = fopen(e_LOG.'rcvstring.txt', 'a+'); fwrite($logfp, $pageName."\n"); fclose($logfp); - -$p_handle = fopen($logPfile, 'r+'); -if($p_handle && flock( $p_handle, LOCK_EX ) ) -{ - $log_file_contents = ''; - while (!feof($p_handle)) // Assemble a string of data - { - $log_file_contents.= fgets($p_handle,1000); - } - $log_file_contents = str_replace(array('<'.'?php','?'.'>'),'',$log_file_contents); - if (eval($log_file_contents) === FALSE && getperms('0')) - { - echo "Error in log file contents: ".$logPfile; - } -} -elseif(getperms('0')) -{ - echo "Couldn't log data to: ".$logPfile; // returned to js popup. - exit; -} - - -$flag = FALSE; -if(array_key_exists($pageName, $pageInfo)) -{ // Existing page - just increment stats - $pageInfo[$pageName]['ttl'] ++; -} -else -{ // First access of page - $url = preg_replace("/".$tagRemove2."/si", "", $self); - if(preg_match("/".$pageDisallow."/i", $url)) return; - $pageInfo[$pageName] = array('url' => $url, 'ttl' => 1, 'unq' => 1); - $flag = TRUE; -} - - - -if(!strstr($ipAddresses, $ip)) -{ /* unique visit */ - if(!$flag) - { - $pageInfo[$pageName]['unq'] ++; - } - $siteUnique ++; - $ipAddresses .= $ip."."; // IP address is stored as hex string - require_once('loginfo.php'); -} - - - - - - -$siteTotal ++; -$info_data = var_export($pageInfo, true); -//$date_stamp = date("z:Y", time()); // Same as '$date' variable - -$data = ""; - -if ($p_handle) -{ - ftruncate($p_handle, 0 ); - fseek( $p_handle, 0 ); - fwrite($p_handle, $data); - fclose($p_handle); -} - -if(LOGSTATS_DEBUG == true) -{ - echo '
Script Completed'; -} - - +' );)"; + referer= ref + color= colord + eself= eself + res= res + err_direct - optional error flag + err_referer - referrer if came via error page + qry = 1 to log query part as well + +// Normally the file is 'silent' - if any errors occur, any error message appears in the page header. +*/ +//error_reporting(0); +// error_reporting(E_ALL); +define('e_MINIMAL',true); +require_once("../../class2.php"); // More secure to include it. +header('Cache-Control: no-cache, must-revalidate'); // See if this discourages browser caching +header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past + +define('LOGSTATS_DEBUG', false); + +// @example url: e107_plugins/log/log.php?lv=cmVmZXJlcj1odHRwJTNBLy9sb2NhbGhvc3QlM0E4MDgwL2UxMDdfMi4wL3N0YXRzJmNvbG91cj0yNCZlc2VsZj1odHRwJTNBLy9sb2NhbGhvc3QlM0E4MDgwL2UxMDdfMi4wL2UxMDdfcGx1Z2lucy9sb2cvc3RhdHMucGhwJTNGMiZyZXM9MTkyMHgxMjAw + +if(LOGSTATS_DEBUG === true) +{ + echo "Debug is Active"; +} + +if (!vartrue($pref['statActivate'])) +{ + if(LOGSTATS_DEBUG === true) + { + echo "Stats log is inactive"; + } + + exit(); +} + + + +//print_r(base64_decode($_GET['lv'])); +define('LOGSTATS_INIT', true); + +// Array of page names which should have individual query values recorded. +// The top level array index is the page name. +// If the top level value is an array, it must be an array of query string beginnings to match. +$pageUnique = array('page' => 1, 'content' => array('content')); + +//$logVals = urldecode(base64_decode($_SERVER['QUERY_STRING'])); +//$logVals = urldecode(base64_decode($_GET['lv'])); + + +// --------------- Reworked for v2.x ------------------------ + + +$logVals = base64_decode($_GET['lv']); +$logVals = filter_var($logVals, FILTER_SANITIZE_URL); + +$logVals .= "&ip=".USERIP; +$logVals .= "&iphost=". @gethostbyaddr(USERIP); +$logVals .= "&lan=".e_LAN; +$logVals .= "&agent=".filter_var($_SERVER['HTTP_USER_AGENT'],FILTER_SANITIZE_STRING); + +parse_str($logVals, $vals); + +$vals['referer'] = urldecode($vals['referer']); +$vals['eself'] = urldecode($vals['eself']); + +if(empty($_SESSION['log_userLoggedPages']) || !in_array($vals['eself'],$_SESSION['log_userLoggedPages'])) +{ + $_SESSION['log_userLoggedPages'][] = $vals['eself']; + $logVals .= "&unique=1"; +} +else +{ + $logVals .= "&unique=0"; +} + + +$logVals = str_replace('%3A',':',$logVals); // make the URLs a bit cleaner, while keeping any urlqueries encoded. + +$lg = e107::getAdminLog(); +$lg->addDebug(print_r($logVals, true)); +$lg->toFile('SiteStats','Statistics Log', true); + +e107::getEvent()->trigger('user_log_stats',$vals); + + +// ------------------------------------ --------------------- + +// We MUST have a timezone set in PHP >= 5.3. This should work for PHP >= 5.1: +// @todo may be able to remove this check once minimum PHP version finalised +if (function_exists('date_default_timezone_get')) +{ + date_default_timezone_set(@date_default_timezone_get()); // Just set a default - it should default to UTC if no timezone set +} + + +//$logfp = fopen(e_LOG.'rcvstring.txt', 'a+'); fwrite($logfp, $logVals."\n"); fclose($logfp); +//$logfp = fopen(e_LOG.'rcvstring.txt', 'a+'); fwrite($logfp, print_r($vals, TRUE)."\n"); fclose($logfp); + +$colour = strip_tags((isset($vals['colour']) ? $vals['colour'] : '')); +$res = strip_tags((isset($vals['res']) ? $vals['res'] : '')); +$self = strip_tags((isset($vals['eself']) ? $vals['eself'] : '')); +$ref = addslashes(strip_tags((isset($vals['referer']) ? $vals['referer'] : ''))); +$logQry = isset($vals['qry']) && $vals['qry']; +$date = date('z.Y', time()); +$logPfile = e_LOG.'logp_'.$date.'.php'; + +//$logString = "Colour: {$colour} Res: {$res} Self: {$self} Referrer: {$ref} ErrCode: {$vals['err_direct']}\n"; +//$logfp = fopen(e_LOG.'rcvstring.txt', 'a+'); fwrite($logfp, $logString); fclose($logfp); + + +// vet resolution and colour depth some more - avoid dud values +if ($res && preg_match("#.*?((\d+)\w+?(\d+))#", $res, $match)) +{ + $res = $match[2].'x'.$match[3]; +} +else +{ + $res = '??'; // Can't decode resolution +} + +if ($colour && preg_match("#.*?(\d+)#",$colour,$match)) +{ + $colour = intval($match[1]); +} +else +{ + $colour='??'; +} + + +if ($err_code = strip_tags((isset($vals['err_direct']) ? $vals['err_direct'] : ''))) +{ + $ref = addslashes(strip_tags(isset($vals['err_referer']) ? $vals['err_referer'] : '')); +// Uncomment the next two lines to create a separate CSV format log of invalid accesses - error code, entered URL, referrer +// $log_string = $err_code.",".$self.",".$ref; +// $logfp = fopen(e_LOG."errpages.csv", 'a+'); fwrite($logfp, $log_string."\n\r"); fclose($logfp); + $err_code .= ':'; +} + +if(strstr($ref, 'admin')) +{ + $ref = FALSE; +} + +$screenstats = $res.'@'.$colour; +$agent = $_SERVER['HTTP_USER_AGENT']; +$ip = e107::getIPHandler()->ipDecode(USERIP); + +$oldref = $ref; // backup for search string being stripped off for referer +if($ref && !strstr($ref, $_SERVER['HTTP_HOST'])) +{ + if(preg_match("#http://(.*?)($|/)#is", $ref, $match)) + { + $ref = $match[0]; + } +} + + +$pageDisallow = "cache|file|eself|admin"; +$tagRemove = "(\\\)|(\s)|(\')|(\")|(eself)|( )|(\.php)|(\.html)"; +$tagRemove2 = "(\\\)|(\s)|(\')|(\")|(eself)|( )"; + +/* +function logGetPageKey($url,$logQry=false,$err_code='') +{ + global $pageDisallow, $tagRemove; + + preg_match("#/(.*?)(\?|$)(.*)#si", $url, $match); + $match[1] = isset($match[1]) ? $match[1] : ''; + $pageName = substr($match[1], (strrpos($match[1], "/")+1)); + + $pageName = preg_replace("/".$tagRemove."/si", "", $pageName); + if($pageName == "") + { + return "index"; + } + + if(preg_match("/".$pageDisallow."/i", $pageName)) + { + return false; + } + + if ($logQry) + { + $pageName .= '+'.$match[3]; // All queries match + } + + $pageName = $err_code.$pageName; // Add the error code at the beginning, so its treated uniquely + + + return $pageName; +}*/ + +require_once(e_PLUGIN."log/consolidate.php"); +$lgc = new logConsolidate; + + +if(!$pageName = $lgc->getPageKey($self,false,$err_code,e_LAN)) +{ + if(LOGSTATS_DEBUG == true) + { + echo 'pageName was empty'; + } + return; +} + +if(LOGSTATS_DEBUG == true) +{ + echo "
File: ".$logPfile; +} + +//$logfp = fopen(e_LOG.'rcvstring.txt', 'a+'); fwrite($logfp, $pageName."\n"); fclose($logfp); + +$p_handle = fopen($logPfile, 'r+'); +if($p_handle && flock( $p_handle, LOCK_EX ) ) +{ + $log_file_contents = ''; + while (!feof($p_handle)) // Assemble a string of data + { + $log_file_contents.= fgets($p_handle,1000); + } + $log_file_contents = str_replace(array('<'.'?php','?'.'>'),'',$log_file_contents); + if (eval($log_file_contents) === FALSE && getperms('0')) + { + echo "Error in log file contents: ".$logPfile; + } +} +elseif(getperms('0')) +{ + echo "Couldn't log data to: ".$logPfile; // returned to js popup. + exit; +} + + +$flag = FALSE; +if(array_key_exists($pageName, $pageInfo)) +{ // Existing page - just increment stats + $pageInfo[$pageName]['ttl'] ++; +} +else +{ // First access of page + $url = preg_replace("/".$tagRemove2."/si", "", $self); + if(preg_match("/".$pageDisallow."/i", $url)) return; + $pageInfo[$pageName] = array('url' => $url, 'ttl' => 1, 'unq' => 1); + $flag = TRUE; +} + + + +if(!strstr($ipAddresses, $ip)) +{ /* unique visit */ + if(!$flag) + { + $pageInfo[$pageName]['unq'] ++; + } + $siteUnique ++; + $ipAddresses .= $ip."."; // IP address is stored as hex string + require_once('loginfo.php'); +} + + + + + + +$siteTotal ++; +$info_data = var_export($pageInfo, true); +//$date_stamp = date("z:Y", time()); // Same as '$date' variable + +$data = ""; + +if ($p_handle) +{ + ftruncate($p_handle, 0 ); + fseek( $p_handle, 0 ); + fwrite($p_handle, $data); + fclose($p_handle); +} + +if(LOGSTATS_DEBUG == true) +{ + echo '
Script Completed'; +} + + ?> \ No newline at end of file diff --git a/e107_plugins/log/log_sql.php b/e107_plugins/log/log_sql.php index 0adf29e14..a067bb225 100644 --- a/e107_plugins/log/log_sql.php +++ b/e107_plugins/log/log_sql.php @@ -1,7 +1,7 @@ -CREATE TABLE logstats ( - log_uniqueid int(11) NOT NULL auto_increment, - log_id varchar(50) NOT NULL default '', - log_data longtext NOT NULL, - PRIMARY KEY (log_uniqueid), - UNIQUE KEY log_id (log_id) +CREATE TABLE logstats ( + log_uniqueid int(11) NOT NULL auto_increment, + log_id varchar(50) NOT NULL default '', + log_data longtext NOT NULL, + PRIMARY KEY (log_uniqueid), + UNIQUE KEY log_id (log_id) ) ENGINE=MyISAM; \ No newline at end of file diff --git a/e107_plugins/log/loginfo.php b/e107_plugins/log/loginfo.php index 1833a6bbc..30157c601 100644 --- a/e107_plugins/log/loginfo.php +++ b/e107_plugins/log/loginfo.php @@ -1,317 +1,317 @@ -'),'',$log_file_contents); - if (eval($log_file_contents) === FALSE) echo "error in log file contents



"; -} -else -{ - echo "Couldn't log data



"; - exit; -} - -$browser = getBrowser($agent); -$os = getOs($agent); - -if($screenstats && $screenstats != "@") -{ - if(array_key_exists($screenstats, $screenInfo)) - { - $screenInfo[$screenstats] ++; - } - else - { - $screenInfo[$screenstats] = 1; - } -} - -if(array_key_exists($browser, $browserInfo)) -{ - $browserInfo[$browser] ++; -} -else -{ - $browserInfo[$browser] = 1; -} - -if(array_key_exists($os, $osInfo)) -{ - $osInfo[$os] ++; -} -else -{ - $osInfo[$os] =1; -} - -/* referer data ... */ -if($ref && !strstr($ref, $_SERVER['HTTP_HOST'])) -{ - if(preg_match("#http://(.*?)($|/)#is", $ref, $match)) - { - $refdom = $match[0]; - if(array_key_exists($refdom, $refInfo)) - { - $refInfo[$refdom]['ttl'] ++; - } - else - { - $refInfo[$refdom] = array('url' => $ref, 'ttl' => 1); - } - } -} - -/* is the referal from Google? If so get search string ... */ -if(preg_match("#q=(.*?)($|&)#is", $oldref, $match)) -{ - $schstr = trim($match[1]); - $schstr = htmlentities(urldecode($schstr)); - if(array_key_exists($schstr, $searchInfo) && $schstr) - { - $searchInfo[$schstr] ++; - } - else - { - $searchInfo[$schstr] = 1; - } -} - -if ($tmp = gethostbyaddr(getenv('REMOTE_ADDR'))) -{ - $host = trim(strtolower(substr($tmp, strrpos($tmp, ".")+1))); - if(!is_numeric($host) && !strstr($host, "calhost")) - { - if(array_key_exists($host, $domainInfo)) - { - $domainInfo[$host] ++; - } - else - { - $domainInfo[$host] =1; - } - } -} - -/* last 20 visitors */ -if(count($visitInfo) >= 20) -{ - $length = 20; - $offset = count($visitInfo)-$length; - $visitInfo = array_slice($visitInfo, $offset, $length); -} - -$visitInfo[$tmp] = array( - 'host' => trim($tmp), - 'date' => time(), - 'os' => trim($os), - 'browser' => trim($browser), - 'screen' => trim($screenstats), - 'referer' => substr(trim($ref), 0, 255), -); - -$data = "'; - - -if ($i_handle) -{ - ftruncate($i_handle, 0); - fseek( $i_handle, 0 ); - fwrite($i_handle, $data); - fclose($i_handle); -} - - -function getBrowser($agent) -{ - // - // All "root" browsers must come at the end of the list, unfortunately. - // Otherwise, browsers based on them will never be seen. - //(But #1997) - // http://www.zytrax.com/tech/web/browser_ids.htm - $browsers = array( - "netcaptor" => array('name' => 'Netcaptor', 'rule' => 'netcaptor[ /]([0-9.]{1,10})'), - "opera" => array('name' => 'Opera Mini', 'rule' => 'Opera[ /]([0-9.]{1,10})(.*)Opera Mini'), - "opera1" => array('name' => 'Opera Mobile', 'rule' => 'Opera[ /]([0-9.]{1,10})(.*)Opera Mobi'), - "opera2" => array('name' => 'Opera', 'rule' => 'opera[ /]([0-9.]{1,10})'), - "chrome" => array('name' => 'Chrome', 'rule' => 'Chrome[ /]([0-9.+]{1,10})'), - "nokia" => array('name' => 'Nokia Browser', 'rule' => 'Nokia([^/]+)/([^ SP]+)'), - "nokia1" => array('name' => 'Nokia Browser', 'rule' => 'Series60|S60/([0-9.]{1,10})'), - "nokia2" => array('name' => 'Nokia Browser', 'rule' => 'Mozilla(.*)SymbianOS(.*)AppleWebKit'), // catch it or it'll become a safari hit! - "aol" => array('name' => 'AOL', 'rule' => 'aol[ /\-]([0-9.]{1,10})'), - "aol2" => array('name' => 'AOL', 'rule' => 'aol[ /\-]?browser'), - "mosaic" => array('name' => 'Mosaic', 'rule' => 'mosaic[ /]([0-9.]{1,10})'), - "k-meleon" => array('name' => 'K-Meleon', 'rule' => 'K-Meleon[ /]([0-9.]{1,10})'), - "konqueror" => array('name' => 'Konqueror', 'rule' => 'konqueror/([0-9.]{1,10})'), - "avantbrowser" => array('name' => 'Avant Browser', 'rule' => 'Avant[ ]?Browser'), - "avantgo" => array('name' => 'AvantGo', 'rule' => 'AvantGo[ /]([0-9.]{1,10})'), - "proxomitron" => array('name' => 'Proxomitron', 'rule' => 'Space[ ]?Bison/[0-9.]{1,10}'), - "lynx" => array('name' => 'Lynx', 'rule' => 'lynx/([0-9a-z.]{1,10})'), - "links" => array('name' => 'Links', 'rule' => 'Links[ /]\(([0-9.]{1,10})'), - "galeon" => array('name' => 'Galeon', 'rule' => 'galeon/([0-9.]{1,10})'), - "abrowse" => array('name' => 'ABrowse', 'rule' => 'abrowse/([0-9.]{1,10})'), - "amaya" => array('name' => 'Amaya', 'rule' => 'amaya/([0-9.]{1,10})'), - "ant" => array('name' => 'ANTFresco', 'rule' => 'ANTFresco[ /]([0-9.]{1,10})'), - "aweb" => array('name' => 'Aweb', 'rule' => 'Aweb[/ ]([0-9.]{1,10})'), - "beonex" => array('name' => 'Beonex', 'rule' => 'beonex/([0-9.]{1,10})'), - "blazer" => array('name' => 'Blazer', 'rule' => 'Blazer[/ ]([0-9.]{1,10})'), - "camino" => array('name' => 'Camino', 'rule' => 'camino/([0-9.+]{1,10})'), - "chimera" => array('name' => 'Chimera', 'rule' => 'chimera/([0-9.+]{1,10})'), - "columbus" => array('name' => 'Columbus', 'rule' => 'columbus[ /]([0-9.]{1,10})'), - "crazybrowser" => array('name' => 'Crazy Browser', 'rule' => 'Crazy Browser[ /]([0-9.]{1,10})'), - "curl" => array('name' => 'Curl', 'rule' => 'curl[ /]([0-9.]{1,10})'), - "deepnet" => array('name' => 'Deepnet Explorer', 'rule' => 'Deepnet Explorer[/ ]([0-9.]{1,10})'), - "dillo" => array('name' => 'Dillo', 'rule' => 'dillo/([0-9.]{1,10})'), - "doris" => array('name' => 'Doris', 'rule' => 'Doris/([0-9.]{1,10})'), - "elinks" => array('name' => 'ELinks', 'rule' => 'ELinks[ /][(]*([0-9.]{1,10})'), - "epiphany" => array('name' => 'Epiphany', 'rule' => 'Epiphany/([0-9.]{1,10})'), - "ibrowse" => array('name' => 'IBrowse', 'rule' => 'ibrowse[ /]([0-9.]{1,10})'), - "icab" => array('name' => 'iCab', 'rule' => 'icab[/ ]([0-9.]{1,10})'), - "ice" => array('name' => 'ICEbrowser', 'rule' => 'ICEbrowser/v?([0-9._]{1,10})'), - "isilox" => array('name' => 'iSiloX', 'rule' => 'iSilox/([0-9.]{1,10})'), - "lotus" => array('name' => 'Lotus Notes', 'rule' => 'Lotus[ -]?Notes[ /]([0-9.]{1,10})'), - "lunascape" => array('name' => 'Lunascape', 'rule' => 'Lunascape[ /]([0-9.]{1,10})'), - "maxthon" => array('name' => 'Maxthon', 'rule' => ' Maxthon[);]'), - "mbrowser" => array('name' => 'mBrowser', 'rule' => 'mBrowser[ /]([0-9.]{1,10})'), - "multibrowser" => array('name' => 'Multi-Browser', 'rule' => 'Multi-Browser[ /]([0-9.]{1,10})'), - "nautilus" => array('name' => 'Nautilus', 'rule' => '(gnome[ -]?vfs|nautilus)/([0-9.]{1,10})'), - "netfront" => array('name' => 'NetFront', 'rule' => 'NetFront[ /]([0-9.]{1,10})$'), - "netpositive" => array('name' => 'NetPositive', 'rule' => 'netpositive[ /]([0-9.]{1,10})'), - "omniweb" => array('name' => 'OmniWeb', 'rule' => 'omniweb/[ a-z]?([0-9.]{1,10})$'), - "oregano" => array('name' => 'Oregano', 'rule' => 'Oregano[0-9]?[ /]([0-9.]{1,10})$'), - "phaseout" => array('name' => 'PhaseOut', 'rule' => 'www.phaseout.net'), - "plink" => array('name' => 'PLink', 'rule' => 'PLink[ /]([0-9a-z.]{1,10})'), - "phoenix" => array('name' => 'Phoenix', 'rule' => 'Phoenix/([0-9.+]{1,10})'), - "proxomitron" => array('name' => 'Proxomitron', 'rule' => 'Space[ ]?Bison/[0-9.]{1,10}'), - "shiira" => array('name' => 'Shiira', 'rule' => 'Shiira/([0-9.]{1,10})'), - "sleipnir" => array('name' => 'Sleipnir', 'rule' => 'Sleipnir( Version)?[ /]([0-9.]{1,10})'), - "slimbrowser" => array('name' => 'SlimBrowser', 'rule' => 'Slimbrowser'), - "staroffice" => array('name' => 'StarOffice', 'rule' => 'staroffice[ /]([0-9.]{1,10})'), - "sunrise" => array('name' => 'Sunrise', 'rule' => 'SunriseBrowser[ /]([0-9.]{1,10})'), - "voyager" => array('name' => 'Voyager', 'rule' => 'voyager[ /]([0-9.]{1,10})'), - "w3m" => array('name' => 'w3m', 'rule' => 'w3m/([0-9.]{1,10})'), - "webtv" => array('name' => 'Webtv', 'rule' => 'webtv[ /]([0-9.]{1,10})'), - "xiino" => array('name' => 'Xiino', 'rule' => '^Xiino[ /]([0-9a-z.]{1,10})'), - "explorer" => array('name' => 'Internet Explorer', 'rule' => '\(compatible; MSIE[ /]([0-9.]{1,10})'), - "safari" => array('name' => 'Safari', 'rule' => 'safari/([0-9.]{1,10})'), - "firefox" => array('name' => 'Firefox', 'rule' => 'Firefox/([0-9.+]{1,10})'), - "netscape" => array('name' => 'Netscape', 'rule' => 'netscape[0-9]?/([0-9.]{1,10})'), - "netscape2" => array('name' => 'Netscape', 'rule' => '^mozilla/([0-4]\.[0-9.]{1,10})'), - "mozilla" => array('name' => 'Mozilla', 'rule' => '^mozilla/[5-9]\.[0-9.]{1,10}.+rv:([0-9a-z.+]{1,10})'), - "mozilla2" => array('name' => 'Mozilla', 'rule' => '^mozilla/([5-9]\.[0-9a-z.]{1,10})'), - "firebird" => array('name' => 'Firebird', 'rule' => 'Firebird/([0-9.+]{1,10})'), - ); - $browser = ""; - foreach($browsers as $key => $info) - { - if (preg_match("#".$info['rule']."#i", $agent, $results)) - { - switch ($key) - { - case 'nokia': - case 'nokia1': - case 'nokia2': - if(strpos(strtolower($agent), 'series60') !== false || strpos($agent, 'S60') !== false ) - { - $info['name'] = 'Nokia S60 OSS Browser'; - } - return ($info['name'].(isset($results[2]) && $results[2] ? ' v'.$results[2] : '')); - break; - - default: - return ($info['name'].(isset($results[1]) && $results[1] ? ' v'.$results[1] : '')); - break; - } - } - } - return ('Unknown'); -} - -function getOs($agent) -{ - // http://www.zytrax.com/tech/web/browser_ids.htm - $os = array( - // mobile come first - latest rules could break the check - "android" => array('name' => 'Android', 'rule' => 'Android\s([0-9.]{1,10})'), - "symbian" => array('name' => 'Symbian', 'rule' => 'symbianOS[ /]?([0-9.]{1,10})'), - "symbian1" => array('name' => 'Symbian', 'rule' => 'series60[ /]'), - "symbian2" => array('name' => 'Symbian', 'rule' => 'Symbian OS Series'), - "windows7" => array('name' => 'Windows 7', 'rule' => 'wi(n|ndows)[ \-]?nt[ /]?6\.1'), - "windowsvista" => array('name' => 'Windows Vista', 'rule' => 'wi(n|ndows)[ \-]?nt[ /]?6\.0'), - "windows2003" => array('name' => 'Windows 2003', 'rule' => 'wi(n|ndows)[ \-]?(2003|nt[ /]?5\.2)'), - "windowsxp" => array('name' => 'Windows XP', 'rule' => 'Windows XP'), - "windowsxp2" => array('name' => 'Windows XP', 'rule' => 'wi(n|ndows)[ \-]?nt[ /]?5\.1'), - "windows2k" => array('name' => 'Windows 2000', 'rule' => 'wi(n|ndows)[ \-]?(2000|nt[ /]?5\.0)'), - "windows95" => array('name' => 'Windows 95', 'rule' => 'wi(n|ndows)[ \-]?95'), - "windowsce" => array('name' => 'Windows CE', 'rule' => 'wi(n|ndows)[ \-]?ce'), - "windowsme" => array('name' => 'Windows ME', 'rule' => 'win 9x 4\.90'), - "windowsme2" => array('name' => 'Windows ME', 'rule' => 'wi(n|ndows)[ \-]?me'), - "windowsnt" => array('name' => 'Windows NT', 'rule' => 'wi(n|ndows)[ \-]?nt[ /]?([0-4][0-9.]{1,10})'), - "windowsnt2" => array('name' => 'Windows NT', 'rule' => 'wi(n|ndows)[ \-]?nt'), - "windows98" => array('name' => 'Windows 98', 'rule' => 'wi(n|ndows)[ \-]?98'), - "windows" => array('name' => 'Windows', 'rule' => 'wi(n|n32|ndows)'), - "linux" => array('name' => 'Linux', 'rule' => 'mdk for ([0-9.]{1,10})'), - "linux2" => array('name' => 'Linux', 'rule' => 'linux[ /\-]([a-z0-9.]{1,10})'), - "linux3" => array('name' => 'Linux', 'rule' => 'linux'), - "macosx" => array('name' => 'MacOS X', 'rule' => 'Mac[ ]?OS[ ]?X'), - "macppc" => array('name' => 'MacOS PPC', 'rule' => 'Mac(_Power|intosh.+P)PC'), - "mac" => array('name' => 'MacOS', 'rule' => 'mac[^hk]'), - "amiga" => array('name' => 'Amiga', 'rule' => 'Amiga[ ]?OS[ /]([0-9.]{1,10})'), - "beos" => array('name' => 'BeOS', 'rule' => 'beos[ a-z]*([0-9.]{1,10})'), - "freebsd" => array('name' => 'FreeBSD', 'rule' => 'free[ \-]?bsd[ /]([a-z0-9.]{1,10})'), - "freebsd2" => array('name' => 'FreeBSD', 'rule' => 'free[ \-]?bsd'), - "irix" => array('name' => 'Irix', 'rule' => 'irix[0-9]*[ /]([0-9.]{1,10})'), - "netbsd" => array('name' => 'NetBSD', 'rule' => 'net[ \-]?bsd[ /]([a-z0-9.]{1,10})'), - "netbsd2" => array('name' => 'NetBSD', 'rule' => 'net[ \-]?bsd'), - "os2" => array('name' => 'OS/2 Warp', 'rule' => 'warp[ /]?([0-9.]{1,10})'), - "os22" => array('name' => 'OS/2 Warp', 'rule' => 'os[ /]?2'), - "openbsd" => array('name' => 'OpenBSD', 'rule' => 'open[ \-]?bsd[ /]([a-z0-9.]{1,10})'), - "openbsd2" => array('name' => 'OpenBSD', 'rule' => 'open[ \-]?bsd'), - "palm" => array('name' => 'PalmOS', 'rule' => 'Palm[ \-]?(Source|OS)[ /]?([0-9.]{1,10})'), - "palm2" => array('name' => 'PalmOS', 'rule' => 'Palm[ \-]?(Source|OS)') - ); - foreach($os as $key => $info) - { - if (preg_match("#".$info['rule']."#i", $agent, $results)) - { - if(strstr($key, "win")) - { - return ($info['name']); - } - else - { - return ($info['name']." ".$results[1]); - } - } - } - return ('Unspecified'); -} +'),'',$log_file_contents); + if (eval($log_file_contents) === FALSE) echo "error in log file contents



"; +} +else +{ + echo "Couldn't log data



"; + exit; +} + +$browser = getBrowser($agent); +$os = getOs($agent); + +if($screenstats && $screenstats != "@") +{ + if(array_key_exists($screenstats, $screenInfo)) + { + $screenInfo[$screenstats] ++; + } + else + { + $screenInfo[$screenstats] = 1; + } +} + +if(array_key_exists($browser, $browserInfo)) +{ + $browserInfo[$browser] ++; +} +else +{ + $browserInfo[$browser] = 1; +} + +if(array_key_exists($os, $osInfo)) +{ + $osInfo[$os] ++; +} +else +{ + $osInfo[$os] =1; +} + +/* referer data ... */ +if($ref && !strstr($ref, $_SERVER['HTTP_HOST'])) +{ + if(preg_match("#http://(.*?)($|/)#is", $ref, $match)) + { + $refdom = $match[0]; + if(array_key_exists($refdom, $refInfo)) + { + $refInfo[$refdom]['ttl'] ++; + } + else + { + $refInfo[$refdom] = array('url' => $ref, 'ttl' => 1); + } + } +} + +/* is the referal from Google? If so get search string ... */ +if(preg_match("#q=(.*?)($|&)#is", $oldref, $match)) +{ + $schstr = trim($match[1]); + $schstr = htmlentities(urldecode($schstr)); + if(array_key_exists($schstr, $searchInfo) && $schstr) + { + $searchInfo[$schstr] ++; + } + else + { + $searchInfo[$schstr] = 1; + } +} + +if ($tmp = gethostbyaddr(getenv('REMOTE_ADDR'))) +{ + $host = trim(strtolower(substr($tmp, strrpos($tmp, ".")+1))); + if(!is_numeric($host) && !strstr($host, "calhost")) + { + if(array_key_exists($host, $domainInfo)) + { + $domainInfo[$host] ++; + } + else + { + $domainInfo[$host] =1; + } + } +} + +/* last 20 visitors */ +if(count($visitInfo) >= 20) +{ + $length = 20; + $offset = count($visitInfo)-$length; + $visitInfo = array_slice($visitInfo, $offset, $length); +} + +$visitInfo[$tmp] = array( + 'host' => trim($tmp), + 'date' => time(), + 'os' => trim($os), + 'browser' => trim($browser), + 'screen' => trim($screenstats), + 'referer' => substr(trim($ref), 0, 255), +); + +$data = "'; + + +if ($i_handle) +{ + ftruncate($i_handle, 0); + fseek( $i_handle, 0 ); + fwrite($i_handle, $data); + fclose($i_handle); +} + + +function getBrowser($agent) +{ + // + // All "root" browsers must come at the end of the list, unfortunately. + // Otherwise, browsers based on them will never be seen. + //(But #1997) + // http://www.zytrax.com/tech/web/browser_ids.htm + $browsers = array( + "netcaptor" => array('name' => 'Netcaptor', 'rule' => 'netcaptor[ /]([0-9.]{1,10})'), + "opera" => array('name' => 'Opera Mini', 'rule' => 'Opera[ /]([0-9.]{1,10})(.*)Opera Mini'), + "opera1" => array('name' => 'Opera Mobile', 'rule' => 'Opera[ /]([0-9.]{1,10})(.*)Opera Mobi'), + "opera2" => array('name' => 'Opera', 'rule' => 'opera[ /]([0-9.]{1,10})'), + "chrome" => array('name' => 'Chrome', 'rule' => 'Chrome[ /]([0-9.+]{1,10})'), + "nokia" => array('name' => 'Nokia Browser', 'rule' => 'Nokia([^/]+)/([^ SP]+)'), + "nokia1" => array('name' => 'Nokia Browser', 'rule' => 'Series60|S60/([0-9.]{1,10})'), + "nokia2" => array('name' => 'Nokia Browser', 'rule' => 'Mozilla(.*)SymbianOS(.*)AppleWebKit'), // catch it or it'll become a safari hit! + "aol" => array('name' => 'AOL', 'rule' => 'aol[ /\-]([0-9.]{1,10})'), + "aol2" => array('name' => 'AOL', 'rule' => 'aol[ /\-]?browser'), + "mosaic" => array('name' => 'Mosaic', 'rule' => 'mosaic[ /]([0-9.]{1,10})'), + "k-meleon" => array('name' => 'K-Meleon', 'rule' => 'K-Meleon[ /]([0-9.]{1,10})'), + "konqueror" => array('name' => 'Konqueror', 'rule' => 'konqueror/([0-9.]{1,10})'), + "avantbrowser" => array('name' => 'Avant Browser', 'rule' => 'Avant[ ]?Browser'), + "avantgo" => array('name' => 'AvantGo', 'rule' => 'AvantGo[ /]([0-9.]{1,10})'), + "proxomitron" => array('name' => 'Proxomitron', 'rule' => 'Space[ ]?Bison/[0-9.]{1,10}'), + "lynx" => array('name' => 'Lynx', 'rule' => 'lynx/([0-9a-z.]{1,10})'), + "links" => array('name' => 'Links', 'rule' => 'Links[ /]\(([0-9.]{1,10})'), + "galeon" => array('name' => 'Galeon', 'rule' => 'galeon/([0-9.]{1,10})'), + "abrowse" => array('name' => 'ABrowse', 'rule' => 'abrowse/([0-9.]{1,10})'), + "amaya" => array('name' => 'Amaya', 'rule' => 'amaya/([0-9.]{1,10})'), + "ant" => array('name' => 'ANTFresco', 'rule' => 'ANTFresco[ /]([0-9.]{1,10})'), + "aweb" => array('name' => 'Aweb', 'rule' => 'Aweb[/ ]([0-9.]{1,10})'), + "beonex" => array('name' => 'Beonex', 'rule' => 'beonex/([0-9.]{1,10})'), + "blazer" => array('name' => 'Blazer', 'rule' => 'Blazer[/ ]([0-9.]{1,10})'), + "camino" => array('name' => 'Camino', 'rule' => 'camino/([0-9.+]{1,10})'), + "chimera" => array('name' => 'Chimera', 'rule' => 'chimera/([0-9.+]{1,10})'), + "columbus" => array('name' => 'Columbus', 'rule' => 'columbus[ /]([0-9.]{1,10})'), + "crazybrowser" => array('name' => 'Crazy Browser', 'rule' => 'Crazy Browser[ /]([0-9.]{1,10})'), + "curl" => array('name' => 'Curl', 'rule' => 'curl[ /]([0-9.]{1,10})'), + "deepnet" => array('name' => 'Deepnet Explorer', 'rule' => 'Deepnet Explorer[/ ]([0-9.]{1,10})'), + "dillo" => array('name' => 'Dillo', 'rule' => 'dillo/([0-9.]{1,10})'), + "doris" => array('name' => 'Doris', 'rule' => 'Doris/([0-9.]{1,10})'), + "elinks" => array('name' => 'ELinks', 'rule' => 'ELinks[ /][(]*([0-9.]{1,10})'), + "epiphany" => array('name' => 'Epiphany', 'rule' => 'Epiphany/([0-9.]{1,10})'), + "ibrowse" => array('name' => 'IBrowse', 'rule' => 'ibrowse[ /]([0-9.]{1,10})'), + "icab" => array('name' => 'iCab', 'rule' => 'icab[/ ]([0-9.]{1,10})'), + "ice" => array('name' => 'ICEbrowser', 'rule' => 'ICEbrowser/v?([0-9._]{1,10})'), + "isilox" => array('name' => 'iSiloX', 'rule' => 'iSilox/([0-9.]{1,10})'), + "lotus" => array('name' => 'Lotus Notes', 'rule' => 'Lotus[ -]?Notes[ /]([0-9.]{1,10})'), + "lunascape" => array('name' => 'Lunascape', 'rule' => 'Lunascape[ /]([0-9.]{1,10})'), + "maxthon" => array('name' => 'Maxthon', 'rule' => ' Maxthon[);]'), + "mbrowser" => array('name' => 'mBrowser', 'rule' => 'mBrowser[ /]([0-9.]{1,10})'), + "multibrowser" => array('name' => 'Multi-Browser', 'rule' => 'Multi-Browser[ /]([0-9.]{1,10})'), + "nautilus" => array('name' => 'Nautilus', 'rule' => '(gnome[ -]?vfs|nautilus)/([0-9.]{1,10})'), + "netfront" => array('name' => 'NetFront', 'rule' => 'NetFront[ /]([0-9.]{1,10})$'), + "netpositive" => array('name' => 'NetPositive', 'rule' => 'netpositive[ /]([0-9.]{1,10})'), + "omniweb" => array('name' => 'OmniWeb', 'rule' => 'omniweb/[ a-z]?([0-9.]{1,10})$'), + "oregano" => array('name' => 'Oregano', 'rule' => 'Oregano[0-9]?[ /]([0-9.]{1,10})$'), + "phaseout" => array('name' => 'PhaseOut', 'rule' => 'www.phaseout.net'), + "plink" => array('name' => 'PLink', 'rule' => 'PLink[ /]([0-9a-z.]{1,10})'), + "phoenix" => array('name' => 'Phoenix', 'rule' => 'Phoenix/([0-9.+]{1,10})'), + "proxomitron" => array('name' => 'Proxomitron', 'rule' => 'Space[ ]?Bison/[0-9.]{1,10}'), + "shiira" => array('name' => 'Shiira', 'rule' => 'Shiira/([0-9.]{1,10})'), + "sleipnir" => array('name' => 'Sleipnir', 'rule' => 'Sleipnir( Version)?[ /]([0-9.]{1,10})'), + "slimbrowser" => array('name' => 'SlimBrowser', 'rule' => 'Slimbrowser'), + "staroffice" => array('name' => 'StarOffice', 'rule' => 'staroffice[ /]([0-9.]{1,10})'), + "sunrise" => array('name' => 'Sunrise', 'rule' => 'SunriseBrowser[ /]([0-9.]{1,10})'), + "voyager" => array('name' => 'Voyager', 'rule' => 'voyager[ /]([0-9.]{1,10})'), + "w3m" => array('name' => 'w3m', 'rule' => 'w3m/([0-9.]{1,10})'), + "webtv" => array('name' => 'Webtv', 'rule' => 'webtv[ /]([0-9.]{1,10})'), + "xiino" => array('name' => 'Xiino', 'rule' => '^Xiino[ /]([0-9a-z.]{1,10})'), + "explorer" => array('name' => 'Internet Explorer', 'rule' => '\(compatible; MSIE[ /]([0-9.]{1,10})'), + "safari" => array('name' => 'Safari', 'rule' => 'safari/([0-9.]{1,10})'), + "firefox" => array('name' => 'Firefox', 'rule' => 'Firefox/([0-9.+]{1,10})'), + "netscape" => array('name' => 'Netscape', 'rule' => 'netscape[0-9]?/([0-9.]{1,10})'), + "netscape2" => array('name' => 'Netscape', 'rule' => '^mozilla/([0-4]\.[0-9.]{1,10})'), + "mozilla" => array('name' => 'Mozilla', 'rule' => '^mozilla/[5-9]\.[0-9.]{1,10}.+rv:([0-9a-z.+]{1,10})'), + "mozilla2" => array('name' => 'Mozilla', 'rule' => '^mozilla/([5-9]\.[0-9a-z.]{1,10})'), + "firebird" => array('name' => 'Firebird', 'rule' => 'Firebird/([0-9.+]{1,10})'), + ); + $browser = ""; + foreach($browsers as $key => $info) + { + if (preg_match("#".$info['rule']."#i", $agent, $results)) + { + switch ($key) + { + case 'nokia': + case 'nokia1': + case 'nokia2': + if(strpos(strtolower($agent), 'series60') !== false || strpos($agent, 'S60') !== false ) + { + $info['name'] = 'Nokia S60 OSS Browser'; + } + return ($info['name'].(isset($results[2]) && $results[2] ? ' v'.$results[2] : '')); + break; + + default: + return ($info['name'].(isset($results[1]) && $results[1] ? ' v'.$results[1] : '')); + break; + } + } + } + return ('Unknown'); +} + +function getOs($agent) +{ + // http://www.zytrax.com/tech/web/browser_ids.htm + $os = array( + // mobile come first - latest rules could break the check + "android" => array('name' => 'Android', 'rule' => 'Android\s([0-9.]{1,10})'), + "symbian" => array('name' => 'Symbian', 'rule' => 'symbianOS[ /]?([0-9.]{1,10})'), + "symbian1" => array('name' => 'Symbian', 'rule' => 'series60[ /]'), + "symbian2" => array('name' => 'Symbian', 'rule' => 'Symbian OS Series'), + "windows7" => array('name' => 'Windows 7', 'rule' => 'wi(n|ndows)[ \-]?nt[ /]?6\.1'), + "windowsvista" => array('name' => 'Windows Vista', 'rule' => 'wi(n|ndows)[ \-]?nt[ /]?6\.0'), + "windows2003" => array('name' => 'Windows 2003', 'rule' => 'wi(n|ndows)[ \-]?(2003|nt[ /]?5\.2)'), + "windowsxp" => array('name' => 'Windows XP', 'rule' => 'Windows XP'), + "windowsxp2" => array('name' => 'Windows XP', 'rule' => 'wi(n|ndows)[ \-]?nt[ /]?5\.1'), + "windows2k" => array('name' => 'Windows 2000', 'rule' => 'wi(n|ndows)[ \-]?(2000|nt[ /]?5\.0)'), + "windows95" => array('name' => 'Windows 95', 'rule' => 'wi(n|ndows)[ \-]?95'), + "windowsce" => array('name' => 'Windows CE', 'rule' => 'wi(n|ndows)[ \-]?ce'), + "windowsme" => array('name' => 'Windows ME', 'rule' => 'win 9x 4\.90'), + "windowsme2" => array('name' => 'Windows ME', 'rule' => 'wi(n|ndows)[ \-]?me'), + "windowsnt" => array('name' => 'Windows NT', 'rule' => 'wi(n|ndows)[ \-]?nt[ /]?([0-4][0-9.]{1,10})'), + "windowsnt2" => array('name' => 'Windows NT', 'rule' => 'wi(n|ndows)[ \-]?nt'), + "windows98" => array('name' => 'Windows 98', 'rule' => 'wi(n|ndows)[ \-]?98'), + "windows" => array('name' => 'Windows', 'rule' => 'wi(n|n32|ndows)'), + "linux" => array('name' => 'Linux', 'rule' => 'mdk for ([0-9.]{1,10})'), + "linux2" => array('name' => 'Linux', 'rule' => 'linux[ /\-]([a-z0-9.]{1,10})'), + "linux3" => array('name' => 'Linux', 'rule' => 'linux'), + "macosx" => array('name' => 'MacOS X', 'rule' => 'Mac[ ]?OS[ ]?X'), + "macppc" => array('name' => 'MacOS PPC', 'rule' => 'Mac(_Power|intosh.+P)PC'), + "mac" => array('name' => 'MacOS', 'rule' => 'mac[^hk]'), + "amiga" => array('name' => 'Amiga', 'rule' => 'Amiga[ ]?OS[ /]([0-9.]{1,10})'), + "beos" => array('name' => 'BeOS', 'rule' => 'beos[ a-z]*([0-9.]{1,10})'), + "freebsd" => array('name' => 'FreeBSD', 'rule' => 'free[ \-]?bsd[ /]([a-z0-9.]{1,10})'), + "freebsd2" => array('name' => 'FreeBSD', 'rule' => 'free[ \-]?bsd'), + "irix" => array('name' => 'Irix', 'rule' => 'irix[0-9]*[ /]([0-9.]{1,10})'), + "netbsd" => array('name' => 'NetBSD', 'rule' => 'net[ \-]?bsd[ /]([a-z0-9.]{1,10})'), + "netbsd2" => array('name' => 'NetBSD', 'rule' => 'net[ \-]?bsd'), + "os2" => array('name' => 'OS/2 Warp', 'rule' => 'warp[ /]?([0-9.]{1,10})'), + "os22" => array('name' => 'OS/2 Warp', 'rule' => 'os[ /]?2'), + "openbsd" => array('name' => 'OpenBSD', 'rule' => 'open[ \-]?bsd[ /]([a-z0-9.]{1,10})'), + "openbsd2" => array('name' => 'OpenBSD', 'rule' => 'open[ \-]?bsd'), + "palm" => array('name' => 'PalmOS', 'rule' => 'Palm[ \-]?(Source|OS)[ /]?([0-9.]{1,10})'), + "palm2" => array('name' => 'PalmOS', 'rule' => 'Palm[ \-]?(Source|OS)') + ); + foreach($os as $key => $info) + { + if (preg_match("#".$info['rule']."#i", $agent, $results)) + { + if(strstr($key, "win")) + { + return ($info['name']); + } + else + { + return ($info['name']." ".$results[1]); + } + } + } + return ('Unspecified'); +} diff --git a/e107_plugins/news/news_months_menu.php b/e107_plugins/news/news_months_menu.php index 0e53fdf0c..89a81955e 100644 --- a/e107_plugins/news/news_months_menu.php +++ b/e107_plugins/news/news_months_menu.php @@ -1,142 +1,142 @@ -retrieve($cString); - -if(!empty($parm)) -{ - if(is_string($parm)) - { - parse_str($parm, $parms); - } - else - { - $parms = $parm; - } - -} - - -if(false === $cached) -{ - if(!function_exists('newsFormatDate')) - { - function newsFormatDate($year, $month, $day = "") { - $date = $year; - $date .= (strlen($month) < 2)?"0".$month: - $month; - $date .= (strlen($day) < 2 && $day != "")?"0".$day: - $day; - return $date; - } - } - - if(!isset($parms['showarchive'])) - { - $parms['showarchive'] = 0; - } - - -// e107::lan('blogcalendar_menu', e_LANGUAGE); // FIXME decide on language file structure (#743) - e107::includeLan(e_PLUGIN.'blogcalendar_menu/languages/'.e_LANGUAGE.'.php'); - - $tp = e107::getParser(); - $sql = e107::getDb(); - - $marray = e107::getDate()->terms('month'); - - - //$parms['year'] = "2011 0"; - if(vartrue($parms['year'])) - { - $date = $parms['year']; - list($cur_year, $cur_month) = explode(" ", date($date)); - $start = mktime(0, 0, 0, 1, 1, $cur_year); - $end = mktime(23, 59, 59, 12, 31, $cur_year); - } - else - { - $date = "Y n"; - list($cur_year, $cur_month) = explode(" ", date($date)); - $start = mktime(0, 0, 0, 1, 1, $cur_year); - $end = time(); - } - - $req_year = $cur_year; - if(e_PAGE == 'news.php' && strstr(e_QUERY, "month")) - { - $tmp = explode('.', e_QUERY); - $item = $tmp[1]; - $req_month = intval(substr($item, 4, 2)); - $req = 'month'; - } - else - { - $req_month = $cur_month; - } - - $xmonth_cnt = array(); - $month_links = array(); - - $sql->db_Mark_Time('News months menu'); - if(!$sql->select("news", "news_id, news_datestamp", "news_class IN (".USERCLASS_LIST.") AND news_datestamp > ".intval($start)." AND news_datestamp < ".intval($end)." ORDER BY news_datestamp DESC")) - { - e107::getCache()->set($cString, ''); - return ''; - } - while ($news = $sql->fetch()) - { - $xmonth = date("n", $news['news_datestamp']); - if ((!isset($month_links[$xmonth]) || !$month_links[$xmonth])) - { - $xmonth_cnt[$xmonth] = 0; - $month_links[$xmonth] = e107::getUrl()->create('news/list/month', 'id='.newsFormatDate($req_year, $xmonth)); - } - $xmonth_cnt[$xmonth]++; - } - - - e107::getDebug()->log($month_links); - - // go over the link array and create the option fields - $menu_text = array(); - $template = e107::getTemplate('news', 'news_menu', 'months', true, true); - $bullet = defined('BULLET') ? THEME_ABS.'images/'.BULLET : THEME_ABS.'images/bullet2.gif'; - $vars = new e_vars(array('bullet' => $bullet)); - foreach($month_links as $index => $val) - { - $vars->addData(array( - 'active' => $index == $req_month ? " active" : '', - 'url' => $val, - 'month' => $marray[$index], - 'count' => $xmonth_cnt[$index], - )); - $menu_text[] = $tp->simpleParse($template['item'], $vars); - } - $cached = $template['start'].implode(varset($template['separator'],''), $menu_text).$template['end']; - - $ns->setContent('text', $cached); - - if($cached) - { - if(!$parms['showarchive']) - { - $footer = ''; - $ns->setContent('footer', $footer); - $cached .= $footer; - - } - $cached = $ns->tablerender(BLOGCAL_L1." ".$req_year, $cached, 'news_months_menu', true); - } - e107::getCache()->set($cString, $cached); -} - -echo $cached; +retrieve($cString); + +if(!empty($parm)) +{ + if(is_string($parm)) + { + parse_str($parm, $parms); + } + else + { + $parms = $parm; + } + +} + + +if(false === $cached) +{ + if(!function_exists('newsFormatDate')) + { + function newsFormatDate($year, $month, $day = "") { + $date = $year; + $date .= (strlen($month) < 2)?"0".$month: + $month; + $date .= (strlen($day) < 2 && $day != "")?"0".$day: + $day; + return $date; + } + } + + if(!isset($parms['showarchive'])) + { + $parms['showarchive'] = 0; + } + + +// e107::lan('blogcalendar_menu', e_LANGUAGE); // FIXME decide on language file structure (#743) + e107::includeLan(e_PLUGIN.'blogcalendar_menu/languages/'.e_LANGUAGE.'.php'); + + $tp = e107::getParser(); + $sql = e107::getDb(); + + $marray = e107::getDate()->terms('month'); + + + //$parms['year'] = "2011 0"; + if(vartrue($parms['year'])) + { + $date = $parms['year']; + list($cur_year, $cur_month) = explode(" ", date($date)); + $start = mktime(0, 0, 0, 1, 1, $cur_year); + $end = mktime(23, 59, 59, 12, 31, $cur_year); + } + else + { + $date = "Y n"; + list($cur_year, $cur_month) = explode(" ", date($date)); + $start = mktime(0, 0, 0, 1, 1, $cur_year); + $end = time(); + } + + $req_year = $cur_year; + if(e_PAGE == 'news.php' && strstr(e_QUERY, "month")) + { + $tmp = explode('.', e_QUERY); + $item = $tmp[1]; + $req_month = intval(substr($item, 4, 2)); + $req = 'month'; + } + else + { + $req_month = $cur_month; + } + + $xmonth_cnt = array(); + $month_links = array(); + + $sql->db_Mark_Time('News months menu'); + if(!$sql->select("news", "news_id, news_datestamp", "news_class IN (".USERCLASS_LIST.") AND news_datestamp > ".intval($start)." AND news_datestamp < ".intval($end)." ORDER BY news_datestamp DESC")) + { + e107::getCache()->set($cString, ''); + return ''; + } + while ($news = $sql->fetch()) + { + $xmonth = date("n", $news['news_datestamp']); + if ((!isset($month_links[$xmonth]) || !$month_links[$xmonth])) + { + $xmonth_cnt[$xmonth] = 0; + $month_links[$xmonth] = e107::getUrl()->create('news/list/month', 'id='.newsFormatDate($req_year, $xmonth)); + } + $xmonth_cnt[$xmonth]++; + } + + + e107::getDebug()->log($month_links); + + // go over the link array and create the option fields + $menu_text = array(); + $template = e107::getTemplate('news', 'news_menu', 'months', true, true); + $bullet = defined('BULLET') ? THEME_ABS.'images/'.BULLET : THEME_ABS.'images/bullet2.gif'; + $vars = new e_vars(array('bullet' => $bullet)); + foreach($month_links as $index => $val) + { + $vars->addData(array( + 'active' => $index == $req_month ? " active" : '', + 'url' => $val, + 'month' => $marray[$index], + 'count' => $xmonth_cnt[$index], + )); + $menu_text[] = $tp->simpleParse($template['item'], $vars); + } + $cached = $template['start'].implode(varset($template['separator'],''), $menu_text).$template['end']; + + $ns->setContent('text', $cached); + + if($cached) + { + if(!$parms['showarchive']) + { + $footer = ''; + $ns->setContent('footer', $footer); + $cached .= $footer; + + } + $cached = $ns->tablerender(BLOGCAL_L1." ".$req_year, $cached, 'news_months_menu', true); + } + e107::getCache()->set($cString, $cached); +} + +echo $cached; diff --git a/e107_plugins/news/templates/news_menu_template.php b/e107_plugins/news/templates/news_menu_template.php index 408461196..7907df5fa 100644 --- a/e107_plugins/news/templates/news_menu_template.php +++ b/e107_plugins/news/templates/news_menu_template.php @@ -1,149 +1,149 @@ -'; -$NEWS_MENU_TEMPLATE['category']['end'] = ''; -$NEWS_MENU_TEMPLATE['category']['item'] = ' -
  • {NEWS_CATEGORY_TITLE}{NEWS_CATEGORY_NEWS_COUNT}
  • -'; - - - - - -// months menu -$NEWS_MENU_TEMPLATE['months']['start'] = '
      '; -$NEWS_MENU_TEMPLATE['months']['end'] = '
    '; -$NEWS_MENU_TEMPLATE['months']['item'] = ' -
  • {month} {count}
  • -'; -//$NEWS_MENU_TEMPLATE['months']['separator'] = '
    '; - - - -// latest menu -$NEWS_MENU_TEMPLATE['latest']['start'] = '
      '; -$NEWS_MENU_TEMPLATE['latest']['end'] = '
    '; // Example: $NEWS_MENU_TEMPLATE['latest']['end'] '
    {currentTotal} from {total}'; -$NEWS_MENU_TEMPLATE['latest']['item'] = '
  • {NEWSTITLE} {NEWSCOMMENTCOUNT}
  • '; - - - - - - -// Other News Menu. -$NEWS_MENU_TEMPLATE['other']['caption'] = TD_MENU_L1; -$NEWS_MENU_TEMPLATE['other']['start'] = ""; - - - - - - - - -// Other News Menu. 2 - -$NEWS_MENU_TEMPLATE['other2']['caption'] = TD_MENU_L2; -$NEWS_MENU_TEMPLATE['other2']['start'] = "
      {SETIMAGE: w=100&h=100&crop=1}"; // set the {NEWSIMAGE} dimensions. -$NEWS_MENU_TEMPLATE['other2']['item'] = "
    • - {NEWSTHUMBNAIL=placeholder} -

      {NEWSTITLELINK}

      -

      ".LAN_READ_MORE." »

      -
      -
    • \n"; - -$NEWS_MENU_TEMPLATE['other2']['end'] = "
    "; - - - - -// Grid Menu -// Moved to news_grid_template.php - - -// $NEWS_MENU_WRAPPER['grid']['NEWSTITLE'] = "{---}"; // example - - -/* Carousel Menu */ - -$NEWS_MENU_TEMPLATE['carousel']['start'] = ' - - '; - - -$NEWS_MENU_TEMPLATE['carousel']['item'] = ' -
    {SETIMAGE: w=800&h=370&crop=1} - {NEWS_IMAGE: class=img-responsive img-fluid} - -
    '; - - - -$NEWS_MENU_TEMPLATE['carousel']['nav'] = '
  • {NEWS_SUMMARY}
  • '; - - -// TODO -$NEWS_MENU_TEMPLATE['archive']['start'] = '
      '; -$NEWS_MENU_TEMPLATE['archive']['end'] = '
    '; - -$NEWS_MENU_TEMPLATE['archive']['year_start'] = "
  • -{YEAR_NAME} -
      -"; -$NEWS_MENU_TEMPLATE['archive']['year_end'] = '
  • '; - -$NEWS_MENU_TEMPLATE['archive']['month_start'] = "
  • - {MONTH_NAME} -
  • '; - -$NEWS_MENU_TEMPLATE['archive']['item'] = " -
  • {ITEM_TITLE}
  • -"; - - +'; +$NEWS_MENU_TEMPLATE['category']['end'] = ''; +$NEWS_MENU_TEMPLATE['category']['item'] = ' +
  • {NEWS_CATEGORY_TITLE}{NEWS_CATEGORY_NEWS_COUNT}
  • +'; + + + + + +// months menu +$NEWS_MENU_TEMPLATE['months']['start'] = '
      '; +$NEWS_MENU_TEMPLATE['months']['end'] = '
    '; +$NEWS_MENU_TEMPLATE['months']['item'] = ' +
  • {month} {count}
  • +'; +//$NEWS_MENU_TEMPLATE['months']['separator'] = '
    '; + + + +// latest menu +$NEWS_MENU_TEMPLATE['latest']['start'] = '
      '; +$NEWS_MENU_TEMPLATE['latest']['end'] = '
    '; // Example: $NEWS_MENU_TEMPLATE['latest']['end'] '
    {currentTotal} from {total}'; +$NEWS_MENU_TEMPLATE['latest']['item'] = '
  • {NEWSTITLE} {NEWSCOMMENTCOUNT}
  • '; + + + + + + +// Other News Menu. +$NEWS_MENU_TEMPLATE['other']['caption'] = TD_MENU_L1; +$NEWS_MENU_TEMPLATE['other']['start'] = ""; + + + + + + + + +// Other News Menu. 2 + +$NEWS_MENU_TEMPLATE['other2']['caption'] = TD_MENU_L2; +$NEWS_MENU_TEMPLATE['other2']['start'] = "
      {SETIMAGE: w=100&h=100&crop=1}"; // set the {NEWSIMAGE} dimensions. +$NEWS_MENU_TEMPLATE['other2']['item'] = "
    • + {NEWSTHUMBNAIL=placeholder} +

      {NEWSTITLELINK}

      +

      ".LAN_READ_MORE." »

      +
      +
    • \n"; + +$NEWS_MENU_TEMPLATE['other2']['end'] = "
    "; + + + + +// Grid Menu +// Moved to news_grid_template.php + + +// $NEWS_MENU_WRAPPER['grid']['NEWSTITLE'] = "{---}"; // example + + +/* Carousel Menu */ + +$NEWS_MENU_TEMPLATE['carousel']['start'] = ' + + '; + + +$NEWS_MENU_TEMPLATE['carousel']['item'] = ' +
    {SETIMAGE: w=800&h=370&crop=1} + {NEWS_IMAGE: class=img-responsive img-fluid} + +
    '; + + + +$NEWS_MENU_TEMPLATE['carousel']['nav'] = '
  • {NEWS_SUMMARY}
  • '; + + +// TODO +$NEWS_MENU_TEMPLATE['archive']['start'] = '
      '; +$NEWS_MENU_TEMPLATE['archive']['end'] = '
    '; + +$NEWS_MENU_TEMPLATE['archive']['year_start'] = "
  • +{YEAR_NAME} +
      +"; +$NEWS_MENU_TEMPLATE['archive']['year_end'] = '
  • '; + +$NEWS_MENU_TEMPLATE['archive']['month_start'] = "
  • + {MONTH_NAME} +
  • '; + +$NEWS_MENU_TEMPLATE['archive']['item'] = " +
  • {ITEM_TITLE}
  • +"; + + diff --git a/e107_plugins/newsfeed/newsfeed_sql.php b/e107_plugins/newsfeed/newsfeed_sql.php index fcd7f6603..728e8d2c9 100644 --- a/e107_plugins/newsfeed/newsfeed_sql.php +++ b/e107_plugins/newsfeed/newsfeed_sql.php @@ -1,12 +1,12 @@ -CREATE TABLE newsfeed ( - newsfeed_id int(10) unsigned NOT NULL auto_increment, - newsfeed_name varchar(150) NOT NULL default '', - newsfeed_url varchar(250) NOT NULL default '', - newsfeed_data longtext NOT NULL, - newsfeed_timestamp int(10) unsigned NOT NULL default '0', - newsfeed_description text NOT NULL, - newsfeed_image varchar(100) NOT NULL default '', - newsfeed_active tinyint(1) unsigned NOT NULL default '0', - newsfeed_updateint int(10) unsigned NOT NULL default '0', - PRIMARY KEY (newsfeed_id) -) ENGINE=MyISAM; +CREATE TABLE newsfeed ( + newsfeed_id int(10) unsigned NOT NULL auto_increment, + newsfeed_name varchar(150) NOT NULL default '', + newsfeed_url varchar(250) NOT NULL default '', + newsfeed_data longtext NOT NULL, + newsfeed_timestamp int(10) unsigned NOT NULL default '0', + newsfeed_description text NOT NULL, + newsfeed_image varchar(100) NOT NULL default '', + newsfeed_active tinyint(1) unsigned NOT NULL default '0', + newsfeed_updateint int(10) unsigned NOT NULL default '0', + PRIMARY KEY (newsfeed_id) +) ENGINE=MyISAM; diff --git a/e107_plugins/newsletter/e_mailout.php b/e107_plugins/newsletter/e_mailout.php index e185d6d1c..33091a9e3 100644 --- a/e107_plugins/newsletter/e_mailout.php +++ b/e107_plugins/newsletter/e_mailout.php @@ -1,262 +1,262 @@ -e107 = e107::getInstance(); - //$this->adminHandler = e107::getRegistry('_mailout_admin'); // Get the mailer admin object - we want to use some of its functions - } - - - /** - * Return data representing the user's selection criteria as entered in the $_POST array. - * - * This is stored in the DB with a saved email. (Just return an empty string or array if this is undesirable) - * The returned value is passed back to selectInit() and showSelect when needed. - * - * @return string Selection data - comma-separated list of category IDs - */ - public function returnSelectors() - { - $res = array(); - if (is_array($_POST['nl_category_sel'])) - { - foreach ($_POST['nl_category_sel'] as $k => $v) - { - $res[] = intval($v); - } - } - return implode(',',$res); - } - - - /** - * Called to initialise data selection routine. - * Needs to save any queries or other information into internal variables, do initial DB queries as appropriate. - * Could in principle read all addresses and buffer them for later routines, if this is more convenient - * - * @param string $selectVals - array of selection criteria as returned by returnSelectors() - * - * @return integer Return number of records available (or 1 if unknown) on success, FALSE on failure - */ - public function selectInit($selectVals = FALSE) - { - $sql = e107::getDb(); - - - if (($selectVals === FALSE) || ($selectVals == '')) - { - return 0; // No valid selector - so no valid records - } - - $qry = "SELECT newsletter_id,newsletter_subscribers FROM `#newsletter` WHERE (`newsletter_parent`=0) AND (`newsletter_id` IN ({$selectVals}))"; -// echo "Selector {$selectVals} query: ".$qry.'
    '; - if (!($sql->gen($qry))) return FALSE; - $this->selectorActive = TRUE; - $this->mail_count = 1; // We have no idea of how many subscribers without reading all relevant DB records - $this->mail_read = 0; - $this->ourDB = new db(); // We'll need our own database object - return $this->mail_count; - } - - - - /** - * Return an email address to add to the recipients list. Return FALSE if no more addresses to add - * - * @return array|boolean FALSE if no more addresses available; else an array: - * 'mail_recipient_id' - non-zero if a registered user, zero if a non-registered user. (Always non-zero from this class) - * 'mail_recipient_name' - user name - * 'mail_recipient_email' - email address to use - * 'mail_target_info' - array of info which might be substituted into email, usually using the codes defined by the editor. - * Array key is the code within '|...|', value is the string for substitution - */ - public function selectAdd() - { - - $sql = e107::getDb(); - - - if (!$this->selectorActive) return FALSE; - - while ($this->selectorActive) - { - if (count($this->targets) == 0) - { // Read in and process another newletter mailing list - if (!($row = $sql->fetch())) - { - $this->selectorActive = FALSE; - return FALSE; // Run out of DB records - } - $this->targets = explode(chr(1), $row['newsletter_subscribers']); - unset($row); - } - foreach ($this->targets as $k => $v) - { - if ($uid = intval(trim($v))) - { // Got a user ID here - look them up and add their data - if ($this->ourDB->select('user', 'user_name,user_email,user_lastvisit', '`user_id`='.$uid)) - { - $row = $this->ourDB->fetch(); - $ret = array('mail_recipient_id' => $uid, - 'mail_recipient_name' => $row['user_name'], // Should this use realname? - 'mail_recipient_email' => $row['user_email'], - 'mail_target_info' => array( - 'USERID' => $uid, - 'DISPLAYNAME' => $row['user_name'], - 'SIGNUP_LINK' => $row['user_sess'], - 'USERNAME' => $row['user_loginname'], - 'USERLASTVISIT' => $row['user_lastvisit'] - ) - ); - $this->mail_read++; - unset($this->targets[$k]); - return $ret; - } - } - unset($this->targets[$k]); - } - } - } - - - /** - * Called once all email addresses read, to do any housekeeping needed - * @return none - */ - public function select_close() - { - // Nothing to do here - } - - - /** - * Called to show current selection criteria, and optionally allow edit - * - * @param boolean $allow_edit is TRUE to allow user to change the selection; FALSE to just display current settings - * @param string $selectVals is the current selection information - in the same format as returned by returnSelectors() - * - * @return array Returns array which is displayed in a table cell - */ - public function showSelect($allow_edit = FALSE, $selectVals = FALSE) - { - $sql = e107::getDb(); - $frm = e107::getForm(); - $var = array(); - - $selects = array_flip(explode(',', $selectVals)); - - if ($sql->select('newsletter', 'newsletter_id, newsletter_title', '`newsletter_parent`=0')) - { - $c=0; - while ($row = $sql->fetch()) - { - $checked = (isset($selects[$row['newsletter_id']])) ? " checked='checked'" : ''; - - if ($allow_edit) - { - $var[$c]['caption'] = $row['newsletter_title']; - $var[$c]['html'] = $frm->checkbox('nl_category_sel[]',$row['newsletter_id'] ,$checked); - } - elseif($checked) - { - $var[$c]['caption'] = $row['newsletter_title']; - $var[$c]['html'] = NLLAN_49; - } - $c++; - } - - return $var; - } - elseif($allow_edit == true) - { - - $var[0]['caption'] = "No newsletters found"; - $var[0]['html'] = ''; - - return $var; - } - else - { - return false; // Return Nothing to avoid confusion. - } - - } - - /** - * Manage Bounces. - */ - public function bounce($data) - { - e107::getLog()->add('Newsletter Bounce', $data, E_LOG_INFORMATIVE, 'BOUNCE'); - } - - - - /** - * Manage Sent. - */ - public function sent($data) // trigerred when email sent from queue. - { - if($data['status'] == 1) // Successfully sent - { - // e107::getLog()->add('Newsletter Sent', $data, E_LOG_INFORMATIVE, 'SENT'); - } - else // Failed - { - // e107::getLog()->add('Newsletter Sent', $data, E_LOG_FATAL, 'SENT'); - } - } - -} - - - +e107 = e107::getInstance(); + //$this->adminHandler = e107::getRegistry('_mailout_admin'); // Get the mailer admin object - we want to use some of its functions + } + + + /** + * Return data representing the user's selection criteria as entered in the $_POST array. + * + * This is stored in the DB with a saved email. (Just return an empty string or array if this is undesirable) + * The returned value is passed back to selectInit() and showSelect when needed. + * + * @return string Selection data - comma-separated list of category IDs + */ + public function returnSelectors() + { + $res = array(); + if (is_array($_POST['nl_category_sel'])) + { + foreach ($_POST['nl_category_sel'] as $k => $v) + { + $res[] = intval($v); + } + } + return implode(',',$res); + } + + + /** + * Called to initialise data selection routine. + * Needs to save any queries or other information into internal variables, do initial DB queries as appropriate. + * Could in principle read all addresses and buffer them for later routines, if this is more convenient + * + * @param string $selectVals - array of selection criteria as returned by returnSelectors() + * + * @return integer Return number of records available (or 1 if unknown) on success, FALSE on failure + */ + public function selectInit($selectVals = FALSE) + { + $sql = e107::getDb(); + + + if (($selectVals === FALSE) || ($selectVals == '')) + { + return 0; // No valid selector - so no valid records + } + + $qry = "SELECT newsletter_id,newsletter_subscribers FROM `#newsletter` WHERE (`newsletter_parent`=0) AND (`newsletter_id` IN ({$selectVals}))"; +// echo "Selector {$selectVals} query: ".$qry.'
    '; + if (!($sql->gen($qry))) return FALSE; + $this->selectorActive = TRUE; + $this->mail_count = 1; // We have no idea of how many subscribers without reading all relevant DB records + $this->mail_read = 0; + $this->ourDB = new db(); // We'll need our own database object + return $this->mail_count; + } + + + + /** + * Return an email address to add to the recipients list. Return FALSE if no more addresses to add + * + * @return array|boolean FALSE if no more addresses available; else an array: + * 'mail_recipient_id' - non-zero if a registered user, zero if a non-registered user. (Always non-zero from this class) + * 'mail_recipient_name' - user name + * 'mail_recipient_email' - email address to use + * 'mail_target_info' - array of info which might be substituted into email, usually using the codes defined by the editor. + * Array key is the code within '|...|', value is the string for substitution + */ + public function selectAdd() + { + + $sql = e107::getDb(); + + + if (!$this->selectorActive) return FALSE; + + while ($this->selectorActive) + { + if (count($this->targets) == 0) + { // Read in and process another newletter mailing list + if (!($row = $sql->fetch())) + { + $this->selectorActive = FALSE; + return FALSE; // Run out of DB records + } + $this->targets = explode(chr(1), $row['newsletter_subscribers']); + unset($row); + } + foreach ($this->targets as $k => $v) + { + if ($uid = intval(trim($v))) + { // Got a user ID here - look them up and add their data + if ($this->ourDB->select('user', 'user_name,user_email,user_lastvisit', '`user_id`='.$uid)) + { + $row = $this->ourDB->fetch(); + $ret = array('mail_recipient_id' => $uid, + 'mail_recipient_name' => $row['user_name'], // Should this use realname? + 'mail_recipient_email' => $row['user_email'], + 'mail_target_info' => array( + 'USERID' => $uid, + 'DISPLAYNAME' => $row['user_name'], + 'SIGNUP_LINK' => $row['user_sess'], + 'USERNAME' => $row['user_loginname'], + 'USERLASTVISIT' => $row['user_lastvisit'] + ) + ); + $this->mail_read++; + unset($this->targets[$k]); + return $ret; + } + } + unset($this->targets[$k]); + } + } + } + + + /** + * Called once all email addresses read, to do any housekeeping needed + * @return none + */ + public function select_close() + { + // Nothing to do here + } + + + /** + * Called to show current selection criteria, and optionally allow edit + * + * @param boolean $allow_edit is TRUE to allow user to change the selection; FALSE to just display current settings + * @param string $selectVals is the current selection information - in the same format as returned by returnSelectors() + * + * @return array Returns array which is displayed in a table cell + */ + public function showSelect($allow_edit = FALSE, $selectVals = FALSE) + { + $sql = e107::getDb(); + $frm = e107::getForm(); + $var = array(); + + $selects = array_flip(explode(',', $selectVals)); + + if ($sql->select('newsletter', 'newsletter_id, newsletter_title', '`newsletter_parent`=0')) + { + $c=0; + while ($row = $sql->fetch()) + { + $checked = (isset($selects[$row['newsletter_id']])) ? " checked='checked'" : ''; + + if ($allow_edit) + { + $var[$c]['caption'] = $row['newsletter_title']; + $var[$c]['html'] = $frm->checkbox('nl_category_sel[]',$row['newsletter_id'] ,$checked); + } + elseif($checked) + { + $var[$c]['caption'] = $row['newsletter_title']; + $var[$c]['html'] = NLLAN_49; + } + $c++; + } + + return $var; + } + elseif($allow_edit == true) + { + + $var[0]['caption'] = "No newsletters found"; + $var[0]['html'] = ''; + + return $var; + } + else + { + return false; // Return Nothing to avoid confusion. + } + + } + + /** + * Manage Bounces. + */ + public function bounce($data) + { + e107::getLog()->add('Newsletter Bounce', $data, E_LOG_INFORMATIVE, 'BOUNCE'); + } + + + + /** + * Manage Sent. + */ + public function sent($data) // trigerred when email sent from queue. + { + if($data['status'] == 1) // Successfully sent + { + // e107::getLog()->add('Newsletter Sent', $data, E_LOG_INFORMATIVE, 'SENT'); + } + else // Failed + { + // e107::getLog()->add('Newsletter Sent', $data, E_LOG_FATAL, 'SENT'); + } + } + +} + + + ?> \ No newline at end of file diff --git a/e107_plugins/newsletter/newsletter_legacy_menu.php b/e107_plugins/newsletter/newsletter_legacy_menu.php index 8f10bc191..f28e9f00a 100644 --- a/e107_plugins/newsletter/newsletter_legacy_menu.php +++ b/e107_plugins/newsletter/newsletter_legacy_menu.php @@ -1,109 +1,109 @@ -select('newsletter', '*', "newsletter_parent='0'")) -{ - return FALSE; -} - -$newsletterArray = $sql->db_getList(); -$requery = false; -//include_lan(e_PLUGIN.'newsletter/languages/'.e_LANGUAGE.'.php'); - -foreach($_POST as $key => $value) -{ - if(strpos($key, 'nlUnsubscribe_') === 0) - { - $subid = str_replace('nlUnsubscribe_', '', $key); - $newsletterArray[$subid]['newsletter_subscribers'] = str_replace(chr(1).USERID, "", $newsletterArray[$subid]['newsletter_subscribers']); - $sql->update('newsletter', "newsletter_subscribers='".$newsletterArray[$subid]['newsletter_subscribers']."' WHERE newsletter_id='".intval($subid)."' "); - $requery = true; - } - elseif(strpos($key, 'nlSubscribe_') === 0) - { - $subid = str_replace("nlSubscribe_", "", $key); - $nl_subscriber_array = $newsletterArray[$subid]['newsletter_subscribers']; - - // prevent double entry of same user id - if (!array_key_exists(USERID, $nl_subscriber_array)) - { - $newsletterArray[$subid]['newsletter_subscribers'] .= chr(1).USERID; - $subscribers_list = array_flip(explode(chr(1), $newsletterArray[$subid]['newsletter_subscribers'])); - sort($subscribers_list); - $new_subscriber_list = implode(chr(1), array_keys($subscribers_list)); - - // remove the possible zero caused by function array_flip - if (substr($new_subscriber_list, 0, 1) == '0') - { - $new_subscriber_list = substr($new_subscriber_list, 1); - } - - $sql->update('newsletter', "newsletter_subscribers='".$new_subscriber_list."' WHERE newsletter_id='".intval($subid)."' "); - $requery = true; - } - } -} - -//global $tp; - -if($requery) -{ - if($sql->select('newsletter', '*', "newsletter_parent='0' ")) - { - $newsletterArray = $sql->db_getList(); - } -} - -$text = ''; -foreach($newsletterArray as $nl) -{ - $text .= "
    -
    - ". - $tp->toHTML($nl['newsletter_title'], TRUE)."
    - ". - $tp->toHTML($nl['newsletter_text'], TRUE)."

    - "; - - if(preg_match("#".chr(1).USERID."(".chr(1)."|$)#si", $nl['newsletter_subscribers'])) - { - $text .= NLLAN_48."

    - toJS(NLLAN_49)."') \" /> - "; - } - else - { - $text .= NLLAN_50." ".USEREMAIL.")

    - toJS(NLLAN_53)."') \" /> - "; - } - $nl_count = $sql->count('newsletter', "(*)", "WHERE newsletter_parent='".$nl['newsletter_id']."' AND newsletter_flag='1'"); - // display issued newsletters - if($nl_count > 0 && USER) - { - $text .= "
    ".NLLAN_72."

    "; - } - $text .= "
    -
    -
    - "; -} - -$ns->tablerender(NLLAN_MENU_CAPTION, $text); +select('newsletter', '*', "newsletter_parent='0'")) +{ + return FALSE; +} + +$newsletterArray = $sql->db_getList(); +$requery = false; +//include_lan(e_PLUGIN.'newsletter/languages/'.e_LANGUAGE.'.php'); + +foreach($_POST as $key => $value) +{ + if(strpos($key, 'nlUnsubscribe_') === 0) + { + $subid = str_replace('nlUnsubscribe_', '', $key); + $newsletterArray[$subid]['newsletter_subscribers'] = str_replace(chr(1).USERID, "", $newsletterArray[$subid]['newsletter_subscribers']); + $sql->update('newsletter', "newsletter_subscribers='".$newsletterArray[$subid]['newsletter_subscribers']."' WHERE newsletter_id='".intval($subid)."' "); + $requery = true; + } + elseif(strpos($key, 'nlSubscribe_') === 0) + { + $subid = str_replace("nlSubscribe_", "", $key); + $nl_subscriber_array = $newsletterArray[$subid]['newsletter_subscribers']; + + // prevent double entry of same user id + if (!array_key_exists(USERID, $nl_subscriber_array)) + { + $newsletterArray[$subid]['newsletter_subscribers'] .= chr(1).USERID; + $subscribers_list = array_flip(explode(chr(1), $newsletterArray[$subid]['newsletter_subscribers'])); + sort($subscribers_list); + $new_subscriber_list = implode(chr(1), array_keys($subscribers_list)); + + // remove the possible zero caused by function array_flip + if (substr($new_subscriber_list, 0, 1) == '0') + { + $new_subscriber_list = substr($new_subscriber_list, 1); + } + + $sql->update('newsletter', "newsletter_subscribers='".$new_subscriber_list."' WHERE newsletter_id='".intval($subid)."' "); + $requery = true; + } + } +} + +//global $tp; + +if($requery) +{ + if($sql->select('newsletter', '*', "newsletter_parent='0' ")) + { + $newsletterArray = $sql->db_getList(); + } +} + +$text = ''; +foreach($newsletterArray as $nl) +{ + $text .= "
    +
    + ". + $tp->toHTML($nl['newsletter_title'], TRUE)."
    + ". + $tp->toHTML($nl['newsletter_text'], TRUE)."

    + "; + + if(preg_match("#".chr(1).USERID."(".chr(1)."|$)#si", $nl['newsletter_subscribers'])) + { + $text .= NLLAN_48."

    + toJS(NLLAN_49)."') \" /> + "; + } + else + { + $text .= NLLAN_50." ".USEREMAIL.")

    + toJS(NLLAN_53)."') \" /> + "; + } + $nl_count = $sql->count('newsletter', "(*)", "WHERE newsletter_parent='".$nl['newsletter_id']."' AND newsletter_flag='1'"); + // display issued newsletters + if($nl_count > 0 && USER) + { + $text .= "
    ".NLLAN_72."

    "; + } + $text .= "
    +
    +
    + "; +} + +$ns->tablerender(NLLAN_MENU_CAPTION, $text); ?> \ No newline at end of file diff --git a/e107_plugins/newsletter/newsletter_sql.php b/e107_plugins/newsletter/newsletter_sql.php index 34dab792b..a45214244 100644 --- a/e107_plugins/newsletter/newsletter_sql.php +++ b/e107_plugins/newsletter/newsletter_sql.php @@ -1,13 +1,13 @@ -CREATE TABLE newsletter ( - newsletter_id int(10) unsigned NOT NULL auto_increment, - newsletter_datestamp int(10) unsigned NOT NULL, - newsletter_title varchar(200) NOT NULL, - newsletter_text text NOT NULL, - newsletter_header text NOT NULL, - newsletter_footer text NOT NULL, - newsletter_subscribers text NOT NULL, - newsletter_parent int(11) NOT NULL, - newsletter_flag tinyint(4) NOT NULL, - newsletter_issue varchar(100) NOT NULL, - PRIMARY KEY (newsletter_id) +CREATE TABLE newsletter ( + newsletter_id int(10) unsigned NOT NULL auto_increment, + newsletter_datestamp int(10) unsigned NOT NULL, + newsletter_title varchar(200) NOT NULL, + newsletter_text text NOT NULL, + newsletter_header text NOT NULL, + newsletter_footer text NOT NULL, + newsletter_subscribers text NOT NULL, + newsletter_parent int(11) NOT NULL, + newsletter_flag tinyint(4) NOT NULL, + newsletter_issue varchar(100) NOT NULL, + PRIMARY KEY (newsletter_id) ) ENGINE=MyISAM; \ No newline at end of file diff --git a/e107_plugins/newsletter/nl_archive.php b/e107_plugins/newsletter/nl_archive.php index 0c1a08389..a04a0d69f 100644 --- a/e107_plugins/newsletter/nl_archive.php +++ b/e107_plugins/newsletter/nl_archive.php @@ -1,137 +1,137 @@ -"; - -if (($action <> 'show' && $action <> 'showp') || ($action_parent_id == 0)) -{ // Action 'show' displays initial page, 'showp' displays following pages - $text .= NLLAN_68; // Invalid parameter defined -} -else -{ - if(!isset($_POST['limit_start'])) - { - $limit_start = 0; - } - else - { - $limit_start = intval($_POST['limit_start']); - } - $nl_count = $sql->count('newsletter', '(*)', "WHERE newsletter_parent='".$action_parent_id."' AND newsletter_flag='1'"); - if ($nl_count > 0) - { - // Retrieve parent info - $sql->select('newsletter', "*", "newsletter_id='".$action_parent_id."'"); - if ($row = $sql->fetch()) - { - $parent_newsletter_title = $tp->toHTML($row['newsletter_title'],true); - $parent_newsletter_text = $tp->toHTML($row['newsletter_text'],true); - $parent_newsletter_header = $tp->toHTML($row['newsletter_header'],true); - $parent_newsletter_footer = $tp->toHTML($row['newsletter_footer'],true); - } - if ($action_nl_id == '' || $action_nl_id == 0) //Show list of sent newsletters - { - // Display parent name - $text .= "{$parent_newsletter_title}
    -
    {$parent_newsletter_text}


    - "; - - // Display list of sent newsletters titles - if ($action == 'showp') - { // This should only be done when action is 'showp' - $limit_start = $limit_start + $page_size; - } - $sql->select('newsletter', '*', "newsletter_parent='".$action_parent_id."' AND newsletter_flag='1' ORDER BY newsletter_datestamp DESC LIMIT ".$limit_start.",".$page_size); - while ($row = $sql->fetch()) - { - $ga = new convert(); - $newsletter_datestamp = $ga->convert_date($row['newsletter_datestamp'], 'long'); - $text .= " - - - - "; - } - $text .= "
    - ".$row['newsletter_issue']." - - ".$tp->toHTML($row['newsletter_title'],true)." - - ".$newsletter_datestamp." -
    "; - if($limit_start + $page_size < $nl_count) - { - $text .= "
    -
    -
    "; - } - } - else // Show requested newsletter - { - $sql->select('newsletter', '*', "newsletter_parent='".$action_parent_id."' AND newsletter_id='".$action_nl_id."' AND newsletter_flag='1'"); - if ($row = $sql->fetch()) - { - // Display parent header - $text .= "$parent_newsletter_title
    -
    $parent_newsletter_text


    - $parent_newsletter_header

    "; - // Display newsletter text - $ga = new convert(); - $newsletter_datestamp = $ga->convert_date($row['newsletter_datestamp'], "long"); - $text .= $newsletter_datestamp."
    ". - $tp->toHTML($row['newsletter_title'],true)."
    -
    ".$tp->toHTML($row['newsletter_text'],true)."


    "; - // Display parent footer - $text .= "$parent_newsletter_footer
    "; - // Display back to newsletter overview button - $text .= "
    "; - } - else - { - $text .= NLLAN_70; //Selected newsletter does not exist - } - } - } - else - { - $text .= NLLAN_69; // No send newsletters available for selected parent - } -} - -$text .= "
    "; - -$ns -> tablerender(NLLAN_67, $text); -require_once(FOOTERF); +"; + +if (($action <> 'show' && $action <> 'showp') || ($action_parent_id == 0)) +{ // Action 'show' displays initial page, 'showp' displays following pages + $text .= NLLAN_68; // Invalid parameter defined +} +else +{ + if(!isset($_POST['limit_start'])) + { + $limit_start = 0; + } + else + { + $limit_start = intval($_POST['limit_start']); + } + $nl_count = $sql->count('newsletter', '(*)', "WHERE newsletter_parent='".$action_parent_id."' AND newsletter_flag='1'"); + if ($nl_count > 0) + { + // Retrieve parent info + $sql->select('newsletter', "*", "newsletter_id='".$action_parent_id."'"); + if ($row = $sql->fetch()) + { + $parent_newsletter_title = $tp->toHTML($row['newsletter_title'],true); + $parent_newsletter_text = $tp->toHTML($row['newsletter_text'],true); + $parent_newsletter_header = $tp->toHTML($row['newsletter_header'],true); + $parent_newsletter_footer = $tp->toHTML($row['newsletter_footer'],true); + } + if ($action_nl_id == '' || $action_nl_id == 0) //Show list of sent newsletters + { + // Display parent name + $text .= "{$parent_newsletter_title}
    +
    {$parent_newsletter_text}


    + "; + + // Display list of sent newsletters titles + if ($action == 'showp') + { // This should only be done when action is 'showp' + $limit_start = $limit_start + $page_size; + } + $sql->select('newsletter', '*', "newsletter_parent='".$action_parent_id."' AND newsletter_flag='1' ORDER BY newsletter_datestamp DESC LIMIT ".$limit_start.",".$page_size); + while ($row = $sql->fetch()) + { + $ga = new convert(); + $newsletter_datestamp = $ga->convert_date($row['newsletter_datestamp'], 'long'); + $text .= " + + + + "; + } + $text .= "
    + ".$row['newsletter_issue']." + + ".$tp->toHTML($row['newsletter_title'],true)." + + ".$newsletter_datestamp." +
    "; + if($limit_start + $page_size < $nl_count) + { + $text .= "
    +
    +
    "; + } + } + else // Show requested newsletter + { + $sql->select('newsletter', '*', "newsletter_parent='".$action_parent_id."' AND newsletter_id='".$action_nl_id."' AND newsletter_flag='1'"); + if ($row = $sql->fetch()) + { + // Display parent header + $text .= "$parent_newsletter_title
    +
    $parent_newsletter_text


    + $parent_newsletter_header

    "; + // Display newsletter text + $ga = new convert(); + $newsletter_datestamp = $ga->convert_date($row['newsletter_datestamp'], "long"); + $text .= $newsletter_datestamp."
    ". + $tp->toHTML($row['newsletter_title'],true)."
    +
    ".$tp->toHTML($row['newsletter_text'],true)."


    "; + // Display parent footer + $text .= "$parent_newsletter_footer
    "; + // Display back to newsletter overview button + $text .= "
    "; + } + else + { + $text .= NLLAN_70; //Selected newsletter does not exist + } + } + } + else + { + $text .= NLLAN_69; // No send newsletters available for selected parent + } +} + +$text .= "
    "; + +$ns -> tablerender(NLLAN_67, $text); +require_once(FOOTERF); ?> \ No newline at end of file diff --git a/e107_plugins/pm/pm_menu.php b/e107_plugins/pm/pm_menu.php index 317fb93bc..a01808ee9 100644 --- a/e107_plugins/pm/pm_menu.php +++ b/e107_plugins/pm/pm_menu.php @@ -1,158 +1,158 @@ - - - ".$pm_inbox['inbox']['new'].' '.LAN_PM_109." - - - - - - - -
    - --- ".LAN_PM." ---
    ".$pm_inbox['inbox']['new'].' '.LAN_PM_109."
    ".$pm_inbox['inbox']['unread'].' '.LAN_PM_37."

    -
    - -
    -
    - - "; - $popuptext = str_replace("\n", '', $popuptext); - $popuptext = str_replace("\t", '', $popuptext); - $text .= " - "; - return $text; - } -} - - -//$pm_prefs = e107::getPlugPref('pm'); -//global $sysprefs, $pm_prefs; - - - -//if(!isset($pm_prefs['perpage'])) -//{ -// $pm_prefs = $sysprefs->getArray('pm_prefs'); - -//} - -require_once(e_PLUGIN.'pm/pm_func.php'); - -e107::getScParser(); - -require_once(e_PLUGIN.'pm/pm_shortcodes.php'); - -//setScVar('pm_handler_shortcodes','pmPrefs', $pm_prefs); -$pmManager = new pmbox_manager($pm_prefs); - -//setScVar('pm_handler_shortcodes','pmManager', $pmManager); - -$template = e107::getTemplate('pm', 'pm_menu'); - -//if(!isset($pm_menu_template)) -if(!isset($template)) -{ - //FIXME URL Breaks - /* - $pm_menu_template = " -
    ".PM_INBOX_ICON." - ".LAN_PLUGIN_PM_INBOX." - {PM_NEWPM_ANIMATE} -
    - {PM_INBOX_TOTAL} ".LAN_PM_36.", {PM_INBOX_UNREAD} ".LAN_PM_37." {PM_INBOX_FILLED} -
    - ".PM_OUTBOX_ICON." - ".LAN_PLUGIN_PM_OUTBOX."
    - {PM_OUTBOX_TOTAL} ".LAN_PM_36.", {PM_OUTBOX_UNREAD} ".LAN_PM_37." {PM_OUTBOX_FILLED} - {PM_SEND_PM_LINK} - {PM_BLOCKED_SENDERS_MANAGE} - "; - */ - -// $pm_menu_template = " - $template = " - ".PM_INBOX_ICON." - ".LAN_PLUGIN_PM_INBOX." - {PM_NEWPM_ANIMATE} -
    - {PM_INBOX_TOTAL} ".LAN_PM_36.", {PM_INBOX_UNREAD} ".LAN_PM_37." {PM_INBOX_FILLED} -
    - ".PM_OUTBOX_ICON." - ".LAN_PLUGIN_PM_OUTBOX."
    - {PM_OUTBOX_TOTAL} ".LAN_PM_36.", {PM_OUTBOX_UNREAD} ".LAN_PM_37." {PM_OUTBOX_FILLED} - {PM_SEND_PM_LINK} - {PM_BLOCKED_SENDERS_MANAGE} - "; -} - -//if(check_class($pm_prefs['pm_class'])) -//{ - $tp = e107::getParser(); - $sc = e107::getScBatch('pm',TRUE, 'pm'); - - $pm_inbox = $pmManager->pm_getInfo('inbox'); - $sc->wrapper('pm_menu'); - -// $txt = "\n".$tp->parseTemplate($pm_menu_template, TRUE, $sc); - $txt = "\n".$tp->parseTemplate($template, TRUE, $sc); - - if($pm_inbox['inbox']['new'] > 0 && $pm_prefs['popup'] && strpos(e_SELF, 'pm.php') === FALSE && $_COOKIE['pm-alert'] != 'ON') - { - - $txt .= pm_show_popup($pm_inbox, $pm_prefs['popup_delay']); - } - - $ns->tablerender(LAN_PM, $txt, 'pm'); -} + + + ".$pm_inbox['inbox']['new'].' '.LAN_PM_109." + + + + + + + +
    + --- ".LAN_PM." ---
    ".$pm_inbox['inbox']['new'].' '.LAN_PM_109."
    ".$pm_inbox['inbox']['unread'].' '.LAN_PM_37."

    +
    + +
    +
    + + "; + $popuptext = str_replace("\n", '', $popuptext); + $popuptext = str_replace("\t", '', $popuptext); + $text .= " + "; + return $text; + } +} + + +//$pm_prefs = e107::getPlugPref('pm'); +//global $sysprefs, $pm_prefs; + + + +//if(!isset($pm_prefs['perpage'])) +//{ +// $pm_prefs = $sysprefs->getArray('pm_prefs'); + +//} + +require_once(e_PLUGIN.'pm/pm_func.php'); + +e107::getScParser(); + +require_once(e_PLUGIN.'pm/pm_shortcodes.php'); + +//setScVar('pm_handler_shortcodes','pmPrefs', $pm_prefs); +$pmManager = new pmbox_manager($pm_prefs); + +//setScVar('pm_handler_shortcodes','pmManager', $pmManager); + +$template = e107::getTemplate('pm', 'pm_menu'); + +//if(!isset($pm_menu_template)) +if(!isset($template)) +{ + //FIXME URL Breaks + /* + $pm_menu_template = " + ".PM_INBOX_ICON." + ".LAN_PLUGIN_PM_INBOX." + {PM_NEWPM_ANIMATE} +
    + {PM_INBOX_TOTAL} ".LAN_PM_36.", {PM_INBOX_UNREAD} ".LAN_PM_37." {PM_INBOX_FILLED} +
    + ".PM_OUTBOX_ICON." + ".LAN_PLUGIN_PM_OUTBOX."
    + {PM_OUTBOX_TOTAL} ".LAN_PM_36.", {PM_OUTBOX_UNREAD} ".LAN_PM_37." {PM_OUTBOX_FILLED} + {PM_SEND_PM_LINK} + {PM_BLOCKED_SENDERS_MANAGE} + "; + */ + +// $pm_menu_template = " + $template = " + ".PM_INBOX_ICON." + ".LAN_PLUGIN_PM_INBOX." + {PM_NEWPM_ANIMATE} +
    + {PM_INBOX_TOTAL} ".LAN_PM_36.", {PM_INBOX_UNREAD} ".LAN_PM_37." {PM_INBOX_FILLED} +
    + ".PM_OUTBOX_ICON." + ".LAN_PLUGIN_PM_OUTBOX."
    + {PM_OUTBOX_TOTAL} ".LAN_PM_36.", {PM_OUTBOX_UNREAD} ".LAN_PM_37." {PM_OUTBOX_FILLED} + {PM_SEND_PM_LINK} + {PM_BLOCKED_SENDERS_MANAGE} + "; +} + +//if(check_class($pm_prefs['pm_class'])) +//{ + $tp = e107::getParser(); + $sc = e107::getScBatch('pm',TRUE, 'pm'); + + $pm_inbox = $pmManager->pm_getInfo('inbox'); + $sc->wrapper('pm_menu'); + +// $txt = "\n".$tp->parseTemplate($pm_menu_template, TRUE, $sc); + $txt = "\n".$tp->parseTemplate($template, TRUE, $sc); + + if($pm_inbox['inbox']['new'] > 0 && $pm_prefs['popup'] && strpos(e_SELF, 'pm.php') === FALSE && $_COOKIE['pm-alert'] != 'ON') + { + + $txt .= pm_show_popup($pm_inbox, $pm_prefs['popup_delay']); + } + + $ns->tablerender(LAN_PM, $txt, 'pm'); +} diff --git a/e107_plugins/pm/pm_sql.php b/e107_plugins/pm/pm_sql.php index a3467c315..56f1e14ae 100755 --- a/e107_plugins/pm/pm_sql.php +++ b/e107_plugins/pm/pm_sql.php @@ -1,24 +1,24 @@ -CREATE TABLE private_msg ( - pm_id int(10) unsigned NOT NULL auto_increment, - pm_from int(10) unsigned NOT NULL default '0', - pm_to varchar(250) NOT NULL default '', - pm_sent int(10) unsigned NOT NULL default '0', /* Date sent */ - pm_read int(10) unsigned NOT NULL default '0', /* Date read */ - pm_subject text NOT NULL, - pm_text text NOT NULL, - pm_sent_del tinyint(1) unsigned NOT NULL default '0', /* Set when can delete */ - pm_read_del tinyint(1) unsigned NOT NULL default '0', /* set when can delete */ - pm_attachments text NOT NULL, - pm_option varchar(250) NOT NULL default '', /* Options associated with PM - '+rr' for read receipt */ - pm_size int(10) unsigned NOT NULL default '0', - PRIMARY KEY (pm_id) -) ENGINE=MyISAM AUTO_INCREMENT=1 ; - -CREATE TABLE private_msg_block ( - pm_block_id int(10) unsigned NOT NULL auto_increment, - pm_block_from int(10) unsigned NOT NULL default '0', - pm_block_to int(10) unsigned NOT NULL default '0', - pm_block_datestamp int(10) unsigned NOT NULL default '0', - pm_block_count int(10) unsigned NOT NULL default '0', /* Counts number of blocked PMs */ - PRIMARY KEY (pm_block_id) -) ENGINE=MyISAM AUTO_INCREMENT=1 ; +CREATE TABLE private_msg ( + pm_id int(10) unsigned NOT NULL auto_increment, + pm_from int(10) unsigned NOT NULL default '0', + pm_to varchar(250) NOT NULL default '', + pm_sent int(10) unsigned NOT NULL default '0', /* Date sent */ + pm_read int(10) unsigned NOT NULL default '0', /* Date read */ + pm_subject text NOT NULL, + pm_text text NOT NULL, + pm_sent_del tinyint(1) unsigned NOT NULL default '0', /* Set when can delete */ + pm_read_del tinyint(1) unsigned NOT NULL default '0', /* set when can delete */ + pm_attachments text NOT NULL, + pm_option varchar(250) NOT NULL default '', /* Options associated with PM - '+rr' for read receipt */ + pm_size int(10) unsigned NOT NULL default '0', + PRIMARY KEY (pm_id) +) ENGINE=MyISAM AUTO_INCREMENT=1 ; + +CREATE TABLE private_msg_block ( + pm_block_id int(10) unsigned NOT NULL auto_increment, + pm_block_from int(10) unsigned NOT NULL default '0', + pm_block_to int(10) unsigned NOT NULL default '0', + pm_block_datestamp int(10) unsigned NOT NULL default '0', + pm_block_count int(10) unsigned NOT NULL default '0', /* Counts number of blocked PMs */ + PRIMARY KEY (pm_block_id) +) ENGINE=MyISAM AUTO_INCREMENT=1 ; diff --git a/e107_plugins/poll/poll_sql.php b/e107_plugins/poll/poll_sql.php index 96f02f44d..67759e535 100644 --- a/e107_plugins/poll/poll_sql.php +++ b/e107_plugins/poll/poll_sql.php @@ -1,18 +1,18 @@ -CREATE TABLE polls ( - poll_id int(10) unsigned NOT NULL auto_increment, - poll_datestamp int(10) unsigned NOT NULL default '0', - poll_start_datestamp int(10) unsigned NOT NULL default '0', - poll_end_datestamp int(10) unsigned NOT NULL default '0', - poll_admin_id int(10) unsigned NOT NULL default '0', - poll_title varchar(250) NOT NULL default '', - poll_options text NOT NULL, - poll_votes text NOT NULL, - poll_ip text NOT NULL, - poll_type tinyint(1) unsigned NOT NULL default '0', - poll_comment tinyint(1) unsigned NOT NULL default '1', - poll_allow_multiple tinyint(1) unsigned NOT NULL default '0', - poll_result_type tinyint(2) unsigned NOT NULL default '0', - poll_vote_userclass smallint(5) unsigned NOT NULL default '0', - poll_storage_method tinyint(1) unsigned NOT NULL default '0', - PRIMARY KEY (poll_id) +CREATE TABLE polls ( + poll_id int(10) unsigned NOT NULL auto_increment, + poll_datestamp int(10) unsigned NOT NULL default '0', + poll_start_datestamp int(10) unsigned NOT NULL default '0', + poll_end_datestamp int(10) unsigned NOT NULL default '0', + poll_admin_id int(10) unsigned NOT NULL default '0', + poll_title varchar(250) NOT NULL default '', + poll_options text NOT NULL, + poll_votes text NOT NULL, + poll_ip text NOT NULL, + poll_type tinyint(1) unsigned NOT NULL default '0', + poll_comment tinyint(1) unsigned NOT NULL default '1', + poll_allow_multiple tinyint(1) unsigned NOT NULL default '0', + poll_result_type tinyint(2) unsigned NOT NULL default '0', + poll_vote_userclass smallint(5) unsigned NOT NULL default '0', + poll_storage_method tinyint(1) unsigned NOT NULL default '0', + PRIMARY KEY (poll_id) ) ENGINE=MyISAM; \ No newline at end of file diff --git a/e107_plugins/rss_menu/rss_sql.php b/e107_plugins/rss_menu/rss_sql.php index e79ebb93d..abb84ab87 100644 --- a/e107_plugins/rss_menu/rss_sql.php +++ b/e107_plugins/rss_menu/rss_sql.php @@ -1,13 +1,13 @@ -CREATE TABLE rss ( - rss_id int(10) unsigned NOT NULL auto_increment, - rss_name varchar(255) NOT NULL default '', - rss_url text NOT NULL, - rss_topicid varchar(255) NOT NULL default '', - rss_path varchar(255) NOT NULL default '', - rss_text longtext NOT NULL, - rss_datestamp int(10) unsigned NOT NULL default '0', - rss_class tinyint(1) unsigned NOT NULL default '0', - rss_limit tinyint(3) unsigned NOT NULL default '0', - PRIMARY KEY (rss_id), - KEY rss_name (rss_name) +CREATE TABLE rss ( + rss_id int(10) unsigned NOT NULL auto_increment, + rss_name varchar(255) NOT NULL default '', + rss_url text NOT NULL, + rss_topicid varchar(255) NOT NULL default '', + rss_path varchar(255) NOT NULL default '', + rss_text longtext NOT NULL, + rss_datestamp int(10) unsigned NOT NULL default '0', + rss_class tinyint(1) unsigned NOT NULL default '0', + rss_limit tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (rss_id), + KEY rss_name (rss_name) ) ENGINE=MyISAM; \ No newline at end of file diff --git a/e107_plugins/siteinfo/e_shortcode.php b/e107_plugins/siteinfo/e_shortcode.php index 7d42e9590..6c3f9404b 100644 --- a/e107_plugins/siteinfo/e_shortcode.php +++ b/e107_plugins/siteinfo/e_shortcode.php @@ -1,223 +1,223 @@ -replaceConstants($_POST['sitebutton']); - } - else - { - $path = (strstr(SITEBUTTON, 'http:') ? SITEBUTTON : e_IMAGE.SITEBUTTON); - } - - if($parm['type'] == 'email' || $parm == 'email') // (retain {} constants ) - { - $h = !empty($parm['h']) ? $parm['h'] : 100; - - $path = e107::getConfig()->get('sitebutton'); - - if(empty($path)) - { - return false; - } - - $realPath = e107::getParser()->replaceConstants($path); - - if(defined('e_MEDIA') && is_writeable(e_MEDIA."temp/") && ($resized = e107::getMedia()->resizeImage($path, e_MEDIA."temp/".basename($realPath),'h='.$h))) - { - $path = e107::getParser()->createConstants($resized); - } - } - - if(!empty($path)) - { - return ''.SITENAME.''; - } - } - - /** - * YYYY is automatically replaced with the current year. - * @return string - */ - function sc_sitedisclaimer() - { - $default = "Proudly powered by e107 which is released under the terms of the GNU GPL License."; - - $text = deftrue('SITEDISCLAIMER',$default); - - $text = str_replace("YYYY", date('Y'), $text); - - return e107::getParser()->toHTML($text, true, 'SUMMARY'); - } - - - function sc_siteurl($parm='') - { - if(strlen(deftrue('SITEURL')) < 3 ) //fixes CLI/cron - { - return e107::getPref('siteurl'); - } - - return SITEURL; - } - - - function sc_sitename($parm='') - { - return ($parm == 'link') ? "".SITENAME."" : SITENAME; - } - - function sc_sitedescription() - { - global $pref; - return SITEDESCRIPTION.(defined('THEME_DESCRIPTION') && $pref['displaythemeinfo'] ? THEME_DESCRIPTION : ''); - } - - function sc_sitetag() - { - return SITETAG; - } - - function sc_sitelogo($parm='') - { - return $this->sc_logo($parm); - } - - function sc_logo($parm = array()) - { - if(is_string($parm)) - { - parse_str(vartrue($parm),$parm); // Optional {LOGO=file=file_name} or {LOGO=link=url} or {LOGO=file=file_name&link=url} - } - // Paths to image file, link are relative to site base - $tp = e107::getParser(); - - $logopref = e107::getConfig('core')->get('sitelogo'); - $logop = $tp->replaceConstants($logopref); - - if(isset($parm['login'])) // Login Page. BC fix. - { - - if(!empty($logopref) && is_readable($logop)) - { - - $logo = $tp->replaceConstants($logopref,'abs'); - $path = $tp->replaceConstants($logopref); - } - elseif(is_readable(THEME."images/login_logo.png")) - { - - $logo = THEME_ABS."images/login_logo.png"; - $path = THEME."images/login_logo.png"; - } - else - { - - - $logo = "{e_IMAGE}logoHD.png"; - $path = e_IMAGE."logoHD.png"; - if(empty($parm['w'])) - { - $parm['w'] = 330; - } - } - } - else - { - - if(vartrue($logopref) && is_readable($logop)) - { - $logo = $tp->replaceConstants($logopref,'abs'); - $path = $tp->replaceConstants($logopref); - } - elseif (isset($file) && $file && is_readable($file)) - { - $logo = e_HTTP.$file; // HTML path - $path = e_BASE.$file; // PHP path - } - else if (is_readable(THEME.'images/e_logo.png')) - { - $logo = THEME_ABS.'images/e_logo.png'; // HTML path - $path = THEME.'images/e_logo.png'; // PHP path - } - elseif(varset($parm['fallback']) == 'sitename') // fallback to - { - return $this->sc_sitename($parm); - } - else - { - $logo = '{e_IMAGE}logoHD.png'; // HTML path - $path = e_IMAGE.'logoHD.png'; // PHP path - } - - } - - $dimensions = array(); - - if((isset($parm['w']) || isset($parm['h']))) - { - // - $dimensions[0] = $parm['w']; - $dimensions[1] = $parm['h']; - - if(empty($parm['noresize']) && !empty($logopref)) // resize by default - avoiding large files. - { - $logo = $logopref; - } - } - elseif(!deftrue('BOOTSTRAP')) - { - $dimensions = getimagesize($path); - } - - $opts = array('alt'=>SITENAME, 'class'=>'logo img-responsive img-fluid'); - - if(!empty($dimensions[0])) - { - $opts['w'] = $dimensions[0]; - - } - - if(!empty($dimensions[1])) - { - $opts['h'] = $dimensions[1]; - } - - // $imageStyle = (empty($dimensions)) ? '' : " style='width: ".$dimensions[0]."px; height: ".$dimensions[1]."px' "; - // $image = "\n"; - - $image = $tp->toImage($logo,$opts); - - if (isset($link) && $link) - { - if ($link == 'index') - { - $image = "".$image.""; - } - else - { - $image = "".$image.""; - } - } - - return $image; - } - - function sc_theme_disclaimer($parm) - { - $pref = e107::getPref(); - return (defined('THEME_DISCLAIMER') && $pref['displaythemeinfo'] ? THEME_DISCLAIMER : ''); - } - -} +replaceConstants($_POST['sitebutton']); + } + else + { + $path = (strstr(SITEBUTTON, 'http:') ? SITEBUTTON : e_IMAGE.SITEBUTTON); + } + + if($parm['type'] == 'email' || $parm == 'email') // (retain {} constants ) + { + $h = !empty($parm['h']) ? $parm['h'] : 100; + + $path = e107::getConfig()->get('sitebutton'); + + if(empty($path)) + { + return false; + } + + $realPath = e107::getParser()->replaceConstants($path); + + if(defined('e_MEDIA') && is_writeable(e_MEDIA."temp/") && ($resized = e107::getMedia()->resizeImage($path, e_MEDIA."temp/".basename($realPath),'h='.$h))) + { + $path = e107::getParser()->createConstants($resized); + } + } + + if(!empty($path)) + { + return ''.SITENAME.''; + } + } + + /** + * YYYY is automatically replaced with the current year. + * @return string + */ + function sc_sitedisclaimer() + { + $default = "Proudly powered by e107 which is released under the terms of the GNU GPL License."; + + $text = deftrue('SITEDISCLAIMER',$default); + + $text = str_replace("YYYY", date('Y'), $text); + + return e107::getParser()->toHTML($text, true, 'SUMMARY'); + } + + + function sc_siteurl($parm='') + { + if(strlen(deftrue('SITEURL')) < 3 ) //fixes CLI/cron + { + return e107::getPref('siteurl'); + } + + return SITEURL; + } + + + function sc_sitename($parm='') + { + return ($parm == 'link') ? "".SITENAME."" : SITENAME; + } + + function sc_sitedescription() + { + global $pref; + return SITEDESCRIPTION.(defined('THEME_DESCRIPTION') && $pref['displaythemeinfo'] ? THEME_DESCRIPTION : ''); + } + + function sc_sitetag() + { + return SITETAG; + } + + function sc_sitelogo($parm='') + { + return $this->sc_logo($parm); + } + + function sc_logo($parm = array()) + { + if(is_string($parm)) + { + parse_str(vartrue($parm),$parm); // Optional {LOGO=file=file_name} or {LOGO=link=url} or {LOGO=file=file_name&link=url} + } + // Paths to image file, link are relative to site base + $tp = e107::getParser(); + + $logopref = e107::getConfig('core')->get('sitelogo'); + $logop = $tp->replaceConstants($logopref); + + if(isset($parm['login'])) // Login Page. BC fix. + { + + if(!empty($logopref) && is_readable($logop)) + { + + $logo = $tp->replaceConstants($logopref,'abs'); + $path = $tp->replaceConstants($logopref); + } + elseif(is_readable(THEME."images/login_logo.png")) + { + + $logo = THEME_ABS."images/login_logo.png"; + $path = THEME."images/login_logo.png"; + } + else + { + + + $logo = "{e_IMAGE}logoHD.png"; + $path = e_IMAGE."logoHD.png"; + if(empty($parm['w'])) + { + $parm['w'] = 330; + } + } + } + else + { + + if(vartrue($logopref) && is_readable($logop)) + { + $logo = $tp->replaceConstants($logopref,'abs'); + $path = $tp->replaceConstants($logopref); + } + elseif (isset($file) && $file && is_readable($file)) + { + $logo = e_HTTP.$file; // HTML path + $path = e_BASE.$file; // PHP path + } + else if (is_readable(THEME.'images/e_logo.png')) + { + $logo = THEME_ABS.'images/e_logo.png'; // HTML path + $path = THEME.'images/e_logo.png'; // PHP path + } + elseif(varset($parm['fallback']) == 'sitename') // fallback to + { + return $this->sc_sitename($parm); + } + else + { + $logo = '{e_IMAGE}logoHD.png'; // HTML path + $path = e_IMAGE.'logoHD.png'; // PHP path + } + + } + + $dimensions = array(); + + if((isset($parm['w']) || isset($parm['h']))) + { + // + $dimensions[0] = $parm['w']; + $dimensions[1] = $parm['h']; + + if(empty($parm['noresize']) && !empty($logopref)) // resize by default - avoiding large files. + { + $logo = $logopref; + } + } + elseif(!deftrue('BOOTSTRAP')) + { + $dimensions = getimagesize($path); + } + + $opts = array('alt'=>SITENAME, 'class'=>'logo img-responsive img-fluid'); + + if(!empty($dimensions[0])) + { + $opts['w'] = $dimensions[0]; + + } + + if(!empty($dimensions[1])) + { + $opts['h'] = $dimensions[1]; + } + + // $imageStyle = (empty($dimensions)) ? '' : " style='width: ".$dimensions[0]."px; height: ".$dimensions[1]."px' "; + // $image = "\n"; + + $image = $tp->toImage($logo,$opts); + + if (isset($link) && $link) + { + if ($link == 'index') + { + $image = "".$image.""; + } + else + { + $image = "".$image.""; + } + } + + return $image; + } + + function sc_theme_disclaimer($parm) + { + $pref = e107::getPref(); + return (defined('THEME_DISCLAIMER') && $pref['displaythemeinfo'] ? THEME_DISCLAIMER : ''); + } + +} ?> \ No newline at end of file diff --git a/e107_plugins/trackback/trackback_sql.php b/e107_plugins/trackback/trackback_sql.php index b0e0e6eb8..fbc9f79cf 100644 --- a/e107_plugins/trackback/trackback_sql.php +++ b/e107_plugins/trackback/trackback_sql.php @@ -1,10 +1,10 @@ -CREATE TABLE trackback ( - `trackback_id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `trackback_pid` int(10) unsigned NOT NULL DEFAULT '0', - `trackback_title` varchar(200) NOT NULL DEFAULT '', - `trackback_excerpt` varchar(250) NOT NULL DEFAULT '', - `trackback_url` varchar(150) NOT NULL DEFAULT '', - `trackback_blogname` varchar(150) NOT NULL DEFAULT '', - PRIMARY KEY (`trackback_id`), - KEY `trackback_pid` (`trackback_pid`) -) ENGINE=MyISAM; +CREATE TABLE trackback ( + `trackback_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `trackback_pid` int(10) unsigned NOT NULL DEFAULT '0', + `trackback_title` varchar(200) NOT NULL DEFAULT '', + `trackback_excerpt` varchar(250) NOT NULL DEFAULT '', + `trackback_url` varchar(150) NOT NULL DEFAULT '', + `trackback_blogname` varchar(150) NOT NULL DEFAULT '', + PRIMARY KEY (`trackback_id`), + KEY `trackback_pid` (`trackback_pid`) +) ENGINE=MyISAM; diff --git a/e107_web/js/chap_script.js b/e107_web/js/chap_script.js index 1530f13b7..b1e9fcc3e 100644 --- a/e107_web/js/chap_script.js +++ b/e107_web/js/chap_script.js @@ -1,410 +1,410 @@ - \ No newline at end of file diff --git a/e107_web/js/core/admin.jquery.css b/e107_web/js/core/admin.jquery.css index 867c2af24..c5742719b 100644 --- a/e107_web/js/core/admin.jquery.css +++ b/e107_web/js/core/admin.jquery.css @@ -1,45 +1,45 @@ - -/* ADMIN specific styling */ -/* -a.media-select-image { margin:5px; border:1px solid rgb(102, 102, 102); width:120px; height:100px; border-radius:4px } - -a.media-select-image:hover { border:1px solid red; } -*/ - - -a.media-select-image, -a.media-select-none { margin:5px; margin-left:0; text-decoration:none; width:80px; height:80px; box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.1), 0px 1px 7px 0px rgba(0, 0, 0, 0.8) inset; background: none repeat scroll 0% 0% rgba(0, 0, 0, 0.3);} - -@media (min-height: 500px){ - a.media-select-image, - a.media-select-none { width:120px; height:120px; } -} - -a.media-select-icon { text-align:center; vertical-align:middle; margin:4px; min-width:48px; min-height:48px; max-width:128px; max-height:128px} -a.media-select-icon:hover { border:1px solid red; } -a.media-select-icon-none { width:48px; height:48px } - - -.media-select-container { padding:10px; } - - .media-select-active { opacity: .5; } - -.e-moving { background-color: silver; } - -legend { display: none; } -.chzn-choices { width: 350px; } -.e-autocomplete { display: none } -.e-expandit-container { margin-top:10px } - -input.helpbox { display:none; } /* legacy BBcode helper box - deprecated and hidden if found in v2.x */ - -a.media-select-none { text-align:center; text-decoration: none } -a.media-select-image-none span { font-size:50px } -a.media-select-icon-none span { font-size:30px } - -@media (min-height: 500px){ - a.media-select-image-none span { font-size:80px } -} - - - + +/* ADMIN specific styling */ +/* +a.media-select-image { margin:5px; border:1px solid rgb(102, 102, 102); width:120px; height:100px; border-radius:4px } + +a.media-select-image:hover { border:1px solid red; } +*/ + + +a.media-select-image, +a.media-select-none { margin:5px; margin-left:0; text-decoration:none; width:80px; height:80px; box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.1), 0px 1px 7px 0px rgba(0, 0, 0, 0.8) inset; background: none repeat scroll 0% 0% rgba(0, 0, 0, 0.3);} + +@media (min-height: 500px){ + a.media-select-image, + a.media-select-none { width:120px; height:120px; } +} + +a.media-select-icon { text-align:center; vertical-align:middle; margin:4px; min-width:48px; min-height:48px; max-width:128px; max-height:128px} +a.media-select-icon:hover { border:1px solid red; } +a.media-select-icon-none { width:48px; height:48px } + + +.media-select-container { padding:10px; } + + .media-select-active { opacity: .5; } + +.e-moving { background-color: silver; } + +legend { display: none; } +.chzn-choices { width: 350px; } +.e-autocomplete { display: none } +.e-expandit-container { margin-top:10px } + +input.helpbox { display:none; } /* legacy BBcode helper box - deprecated and hidden if found in v2.x */ + +a.media-select-none { text-align:center; text-decoration: none } +a.media-select-image-none span { font-size:50px } +a.media-select-icon-none span { font-size:30px } + +@media (min-height: 500px){ + a.media-select-image-none span { font-size:80px } +} + + + diff --git a/e107_web/js/core/admin.jquery.js b/e107_web/js/core/admin.jquery.js index 0d04af294..61d0b213e 100644 --- a/e107_web/js/core/admin.jquery.js +++ b/e107_web/js/core/admin.jquery.js @@ -1,1099 +1,1099 @@ -var e107 = e107 || {'settings': {}, 'behaviors': {}}; - -(function ($) -{ - - /** - * Initializes click event on '.e-modal' elements. - * - * @type {{attach: e107.behaviors.eModalAdmin.attach}} - */ - e107.behaviors.eModalAdmin = { - attach: function (context, settings) - { - $(context).find('.e-modal').once('e-modal-admin').each(function () - { - var $that = $(this); - - $that.on('click', function () - { - var $this = $(this); - - if($this.attr('data-cache') === 'false') - { - $('#uiModal').on('shown.bs.modal', function () - { - $(this).removeData('bs.modal'); - }); - } - - var url = $this.attr('href'); - var caption = $this.attr('data-modal-caption'); - var height = ($(window).height() * 0.7) - 120; - - - if(caption === undefined) - { - caption = ''; - } - - $('.modal-body').html('
    '); - $('.modal-caption').html(caption + ' '); - $('.modal').modal('show'); - - $("#e-modal-iframe").on("load", function () - { - $('#e-modal-loading').hide(); - - if($this.attr('data-modal-submit')) - { - var buttonCaption = $('#e-modal-iframe').contents().find('#etrigger-submit').text(); // copy submit button caption from iframe form. - - var buttonClass = $('#e-modal-iframe').contents().find('#etrigger-submit').attr('data-modal-submit-class'); // co - if(buttonCaption) - { - $('#e-modal-submit').text(buttonCaption).fadeIn(); // display the button in the modal footer. - } - - if(buttonClass) - { - $('#e-modal-submit').addClass(buttonClass); - } - - - $('#e-modal-iframe').contents().find('.buttons-bar').hide(); // hide buttons in the iframe's form. - } - - }); - - - - return false; - }); - }); - } - }; - - /** - * Run tips on .field-help. - * - * @type {{attach: e107.behaviors.fieldHelpTooltip.attach}} - */ - e107.behaviors.fieldHelpTooltip = { - attach: function (context, settings) - { - var selector = 'div.tbox,div.checkboxes,input,textarea,select,label,.e-tip,div.form-control'; - - $(context).find(selector).once('field-help-tooltip').each(function () - { - var $this = $(this); - var $fieldHelp = $this.nextAll(".field-help"); - var placement = 'bottom'; - - if($this.is("textarea")) - { - placement = 'top'; - } - - var custPlace = $fieldHelp.attr('data-placement'); // ie top|left|bottom|right - - if(custPlace !== undefined) - { - placement = custPlace; - } - - $fieldHelp.hide(); - - $this.tooltip({ - title: function () - { - return $fieldHelp.html(); - }, - fade: true, - html: true, - opacity: 1.0, - placement: placement, - container: 'body', - delay: { - show: 300, - hide: 600 - } - }); - }); - } - }; - -})(jQuery); - -(function (jQuery) -{ - - /** - * jQuery extension to make admin tab 'fadeIn' with 'display: inline-block'. - * - * @param displayMode - * A string determining display mode for element after the animation. - * Default: 'inline-block'. - * @param duration - * A string or number determining how long the animation will run. - * Default: 400. - */ - jQuery.fn.fadeInAdminTab = function (displayMode, duration) - { - var $this = $(this); - - if($this.css('display') !== 'none') - { - return; - } - - displayMode = displayMode || 'inline-block'; - duration = duration || 400; - - $this.fadeIn(duration, function () - { - $this.css('display', displayMode); - }); - }; - -})(jQuery); - - -$(document).ready(function() -{ - - $('#e-modal-submit').click(function () { - $('#e-modal-iframe').contents().find('#etrigger-submit').trigger('click'); - - var type = $(this).data('loading-icon'); - var orig = $(this).text(); - - var caption = ""; - caption += "" + orig + ""; - - $(this).html(caption); - - $('#e-modal-iframe').on('load', function(){ - - var buttonFound = $('#e-modal-iframe').contents().find('#etrigger-submit'); - - if(buttonFound.length === 0) // disable resubmitting if not button found after submit. - { - $('#e-modal-submit').fadeOut(1000); - } - - $('#e-modal-submit').text(orig); // remove spinner. - - }); - - }); - - $('[data-dismiss="modal"]').click(function(){ // hide button for next modal popup usage. - - $('#e-modal-submit').hide(1000); - - }); - - - - - - - - $('form').h5Validate( - { errorClass: 'has-error' } - ); // allow older browsers to use html5 validation. - - // Change hash when a tab changes - $('.nav-tabs a').on('shown', function (event) { - var hash = event.target.href.toString().split('#')[1], form = $(event.target).parents('form')[0]; - window.location.hash = '/' + hash; - if(form) { - $(form).attr('action', $(form).attr('action').split('#')[0] + '#/' + hash); - } - }); - - // tabs hash - if(/^#\/\w+/.test(window.location.hash)) { - var hash = window.location.hash.substr(2); - if(hash.match('^tab')){ $('.nav-tabs a[href=#' + hash + ']').tab('show'); } - } - - $('.e-typeahead').each( function(){ - - var id = $(this).attr("id"); - var name = '#' + id.replace('-usersearch', ''); - var newval = $(this).attr("data-value"); - - $(this).typeahead({ - source: $(this).attr("data-source"), - updater: function(text, type){ - if(type === 'value') - { - $(name).val(text); - } - return text; - } - }); - }); - - /* Switch to Tab containing invalid form field. */ - $('input[type=submit],button[type=submit]').on('click', function() { - - var id = $(this).closest('form').attr('id'); - var found = false; - - $('#'+id).find('input:invalid,select:invalid,textarea:invalid').each(function(index, node) { - - var tab = $('#'+node.id).closest('.tab-pane').attr('id'); - - if(tab && (found === false)) - { - $('a[href="#'+tab+'"]').tab('show'); - found = true; - // alert(node.id+' : '+tab + ' '.index); - } - // var label = $('label[for=' + node.id + ']'); - }); - - return true; - }); - - - - // run tips on title attribute. - $(".e-tip").each(function() { - - - var tip = $(this).attr('title'); - if(!tip) - { - return; - } - - var pos = $(this).attr('data-placement'); - if(!pos) - { - pos = 'top'; - } - - $(this).tooltip({opacity:1.0,fade:true, placement: pos}); - // $(this).css( 'cursor', 'pointer' ) - }); - - - $("#uiModal").draggable({ - handle: ".modal-header" - }); - - - - - $('div.e-container').editable({ - selector: '.e-editable', - params: function(params) { - params.token = $(this).attr('data-token'); - return params; - }, - display: function (value, sourceData) - { - // HTML entities decoding... fix for: - // @see https://github.com/e107inc/e107/issues/2351 - $.each(sourceData, function (index, element) - { - element.text = $("
    ").html(element.text).text(); - sourceData[index] = element; - }); - - // Display checklist as comma-separated values. - var html = []; - var checked = $.fn.editableutils.itemsByValue(value, sourceData); - - if(checked.length) - { - $.each(checked, function (i, v) - { - html.push($.fn.editableutils.escape(v.text)); - }); - - $(this).html(html.join(', ')); - } - else - { - $(this).text(value); - } - } - }); - -// $('.e-editable').editable(); - - // Fix for boostrap modal cache. - - // $('.modal').on('hidden',function(){ - // $(this).removeData('.modal'); - // $('#uiModal .modal-label').text('Loading'); - // $('#uiModal .modal-body').html('default_body'); - // }); - - $('body').on('hidden', '.modal', function () { - $(this).removeData('modal'); - $('#uiModal .modal-label').text('Loading...'); - $('#uiModal .modal-body').html(' '); - }); - - - - - $('a[data-toggle="modal"]').on('click', function() - { - var link = $(this).attr('href'); - var caption = $(this).attr('data-modal-caption'); - var height = ($(window).height() * 0.9) - 50; - - $('#uiModal .modal-caption').text(caption); - $('.modal').height(height); - // $('#uiModal .modal-label').text('Loading...'); - // $('#uiModal .modal-body').html(link); - // alert(caption); - } - ); - - - $('button[data-loading-text],a[data-loading-text]').on('click', function() - { - var caption = $(this).attr('data-loading-text'); - $(this).removeClass('btn-success'); - $(this).removeClass('btn-primary'); - $(this).html(caption); - if($(this).attr('data-disable') == 'true') - { - $(this).attr('disabled', 'disabled'); - } - return true; - } - ); - - $('input[data-loading-text]').on('click', function() - { - var caption = $(this).attr('data-loading-text'); - $(this).val(caption); - $(this).removeClass('btn-success'); - $(this).removeClass('btn-primary'); - //$(this).attr('disabled', 'disabled').val(caption); - return true; - } - ); - - - $('a[data-toggle-sidebar]').on('click', function(e) - { - e.preventDefault(); - - var $leftPanel = $(".admin-left-panel"); - var $rightPanel = $(".admin-right-panel"); - - if ($rightPanel.hasClass('col-md-12')) - { - $rightPanel.toggleClass("col-md-9 col-md-12"); - $rightPanel.toggleClass("col-lg-10 col-lg-12"); - $leftPanel.toggle(1000); - } - else - { - $leftPanel.toggle(1000, function() { - $rightPanel.toggleClass("col-md-9 col-md-12"); - $rightPanel.toggleClass("col-lg-10 col-lg-12"); - }); - } - - }); - - - - /* InfoPanel Comment approval and deletion */ - $(document).on("click", "button[data-comment-action]", function(){ - - var url = $(this).attr("data-target"); - var action = $(this).attr('data-comment-action'); - var id = $(this).attr("data-comment-id"); - var next = $('#comment-'+ id).nextAll('.hide').attr("id"); - - $.ajax({ - type: 'POST', - url: url + '?ajax_used=1&mode='+action, - data: { itemid: id }, - success: function(data) { - var a = $.parseJSON(data); - // alert(data); - if(!a.error) - { - $('#comment-'+ id).hide(800, function () { - $('#'+next).show('slow'); - $('#'+next).removeClass('hide'); - }); - - } - - } - }); - - return false; - - }); - - - - - var progresspump = null; - - $('.e-progress-cancel').on('click', function(e) - { - clearInterval(progresspump); - var target = $(this).attr('data-progress-target'); - $("#"+target).closest('.progress').removeClass("active"); - progresspump = null; - alert('stopped'); - }); - - $('.e-progress').on('click', function(e) - { - // alert('Process Started'); - - var target = $(this).attr('data-progress-target'); - var script = $(this).attr('data-progress'); - var show = $(this).attr('data-progress-show'); - var hide = $(this).attr('data-progress-hide'); - var mode = $(this).attr('data-progress-mode'); - var interval = $(this).attr('data-progress-interval'); - - if(interval === undefined) - { - interval = 1000; - } - - $("#"+target).css('width','1%'); // so we know it's running. - - progresspump = setInterval(function(){ - - $.get(script, { mode: mode }).done( function(data){ - - // alert(data); - $("#"+target).css('width', data+'%'); // update the progress bar width */ - $("#"+target).html(data+'%'); // display the numeric value */ - - - data = parseInt(data); - - if(data > 99.999) { - - clearInterval(progresspump); - $("#"+target).closest('.progress').removeClass("active"); - - $("#"+target).html("Done"); - - if(hide !== 'undefined') - { - $('#'+hide).hide(); - } - - if(show !== 'undefined') - { - $('#'+show).show('slow'); - } - - - } - - }); - - }, interval); - }); - - - - - - - /* - - $('a[data-toggle="modal"]').on('click', function() - { - $(this).removeData('modal'); - $('#uiModal .modal-header').text($(this).attr('title')); - var link = $(this).attr('href'); - alert(link); - $('#uiModal .modal-body').html( 'table' ); - //return false; - - return this; - - $('#uiModal .modal-body').load(link, function(response, status, xhr) - { - if (status === 'error') - { - //console.log('got here'); - $('#uiModal .modal-body').html('

    Oh boy

    Sorry, but there was an error:' + xhr.status + ' ' + xhr.statusText+ '

    '); - } - return false; - return this; - } - ) - - }); - - */ - - - - - - - $('.e-noclick').click(function(e) { - e.stopPropagation(); - }); - - - // BC Compatible - $("select.tbox").each(function() { - - var multi = $(this).attr('multiple'); - - if(multi === undefined) - { - // $(this).selectpicker(); // causes HTML5 validation alert to be hidden. - return; - } - else - { - $(this).multiselect({ buttonClass: 'btn btn-default'} ); - } - - }); - - - - // $(".e-spinner").spinner(); //FIXME breaks tooltips etc. - - - $(document).on("click", ".e-alert", function(){ - - var message = $(this).html(); - alert(message); - $("#uiAlert").val(message); - $("#uiAlert").alert(); - $("#uiAlert").fadeIn('slow'); - window.setTimeout(function() { $("#uiAlert").alert('close'); }, 4000); - - }); - - - - - - $(".e-radio-multi").each(function() { - // $(this).nextAll(".field-help").hide(); - // $(this).nextAll(":input").tipsy({title: 'hello'}); - - }); - - // $(".e-tags").tag(); - - - - // Decorate - $(".adminlist tr:even").addClass("even"); - $(".adminlist tr:odd").addClass("odd"); - $(".adminlist tr:first").addClass("first"); - $(".adminlist tr:last").addClass("last"); - - - - // Admin Prefs Navigation - - $(".plugin-navigation a").click(function () { - $(".plugin-navigation a").each(function(index) { - var ot = $(this).attr("href"); - if (ot.split('#')[1]) { - $(ot).hide().removeClass('e-hideme'); - } - $(this).closest("li").removeClass("active"); - $(this).switchClass( "link-active", "link", 0 ); - }); - var id = $(this).attr("href"), hash = id.split('#')[1], form = $('.admin-menu')[0]; // FIXME - a better way to detect the page form - - $(this).switchClass( "link", "link-active", 30 ); - $(this).closest("li").addClass("active"); - - // 'remember' the active navigation pane - if(hash) { - $(id).removeClass('e-hideme').show({ - effect: "slide" - }); - window.location.hash = 'nav-' + hash; - if(form) { - - // $(form).attr('action', $(form).attr('action').split('#')[0] + '#nav-' + hash); // breaks menu-manager nav. - } - return false; - } - }); - - // plugin navigation hash - if(/^#nav-+/.test(window.location.hash)) { - $("a[href='" + window.location.hash.replace('nav-', '') + "']").click(); - } - - // backend - /* - $(".e-password").pwdMeter({ - minLength: 6, - displayGeneratePassword: true, - generatePassText: "Generate", - randomPassLength: 12 - });*/ - - - - // Sorting - var fixHelper = function(e, ui) { - ui.closest("tr").switchClass( "odd", "highlight-odd e-sort", 0 ); - ui.closest("tr").switchClass( "even", "highlight-even e-sort", 0 ); - ui.children().each(function() { - $(this).width($(this).width()); - // $(this).closest("tr").switchClass( "odd", "highlight-odd", 0 ); - // $(this).closest("tr").switchClass( "even", "highlight-even", 0 ); - }); - return ui; - }; - - $("#e-sort").sortable({ - helper: fixHelper, - cursor: "move", - opacity: 0.9, - handle: ".e-sort", - distance: 20, - containment: "parent", - stop: function(e,ui) { - var allItems = $(this).sortable("toArray"); - var newSortValue = allItems.indexOf( $(ui.item).attr("id") ); - // alert($(ui.item).attr("id") + " was moved to index " + newSortValue); - $(".highlight-even").switchClass( "highlight-even", "even", 600 ); - $(".highlight-odd").switchClass( "highlight-odd", "odd", 600 ); - $("tr.e-sort").removeClass( "e-sort"); - - }, - - update: function(event, ui) { - var allItems = $(this).sortable("toArray"); - // console.log(allItems); - var neworder = allItems.indexOf( $(ui.item).attr("id") ); - var linkid = $(ui.item).attr("id"); - // $("td").removeClass("e-moving","slow"); - - var script = $(".sort-trigger:first").attr("data-target"); - - $.ajax({ - type: "POST", - url: script, - data: { all: allItems, linkid: linkid, neworder: neworder } - // data: { linkid: linkid, neworder: neworder } - }).done(function( msg ) { - - // alert("Posted: "+allItems+" Updated: "+ msg ); - }); - - } - - }); - // }).disableSelection(); // causes issue with admin->users drop-down selection. - - - // Check ALl Button - $("#e-check-all").click(function(){ - $('input[type="checkbox"]').attr("checked", "checked"); - }); - - // Uncheck all button. - $("#e-uncheck-all").click(function(){ - $('input[type="checkbox"]').removeAttr("checked"); - }); - - - - // Check-All checkbox toggle - $("input.toggle-all").click(function(evt) { - var selector = 'input[type="checkbox"].checkbox'; - - if($(this).val().indexOf('jstarget:') === 0) { - selector = 'input[type="checkbox"][name^="' + $(this).val().split(/jstarget\:/)[1] + '"]'; - } - - if($(this).is(":checked")){ - //$(selector).attr("checked", "checked"); - $(selector).prop('checked', true); - } - else{ - $(selector).prop('checked',false); - // $(selector).removeAttr("checked"); - } - }); - - // highlight checked row - $(".adminlist input[type='checkbox']").click(function(evt){ - - if(this.checked) - { - $(this).closest("tr.odd").switchClass( "odd", "highlight-odd", 50 ); - $(this).closest("tr.even").switchClass( "even", "highlight-even", 50 ); - } - else - { - $(this).closest("tr.highlight-odd").switchClass( "highlight-odd", "odd", 300 ); - $(this).closest("tr.highlight-even").switchClass( "highlight-even", "even", 300 ); - } - - }); - - - - - // Basic Delete Confirmation - /* - $('input.delete,button.delete,a[data-confirm]').click(function(){ - answer = confirm($(this).attr("data-confirm")); - return answer; // answer is a boolean - }); - */ - $(".e-confirm").click(function(){ - answer = confirm($(this).attr("title")); - return answer; // answer is a boolean - }); - - - // see boot.php for main processing. (works only in admin) - $(".e-sef-generate").click(function(){ - - src = $(this).attr("data-src"); - target = $(this).attr("data-target"); - toconvert = $('#'+src).val(); - script = window.location; - - $.ajax({ - type: "POST", - url: script, - data: { source: toconvert, mode: 'sef' } - - }).done(function( data ) { - - var a = $.parseJSON(data); - // alert(a.converted); - if(a.converted) - { - $('#'+target).val(a.converted); - - // $('#uiAlert').notify({ - // type: 'success', - // message: { text: 'Completed' }, - // fadeOut: { enabled: true, delay: 2000 } - // }).show(); - - } - }); - - }); - - - $('body').on('slid.bs.carousel', '.carousel', function(){ - var currentIndex = $(this).find('.active').index(); - var text = (currentIndex + 1); - var id = $(this).attr('id') + '-index'; // admin-ui-carousel-index etc. - $('#'+id).text(text); - - // this takes commented content for each carousel slide and enables it, one slide at a time as we scroll. - - $(this).find('.item').each(function(index, node) - { - var content = $(this).contents(); - - var item = content[0]; - - if(item.nodeType === 8) // commented code @see e_media::browserCarousel() using ' - - - - -
    - - - -
    -
    -

    {stage_title}

    -
    -
    - {stage_content} -
    -
    - - - - -
    {debug_info}
    -
    - - - - - - - - - - - - - '; - return $data; -} - -/** - * Render a Fatal error and halt installation. - */ -function die_fatal_error($error) -{ - - define("e_IMAGE","e107_images/"); - define("e_JS","e107_web/js/"); - define("e_THEME", "e107_themes/"); - define("e_LANGUAGEDIR", "e107_languages/"); - - include(e_LANGUAGEDIR."English/English.php"); - include(e_LANGUAGEDIR."English/lan_installer.php"); - - $var = array(); - $var["installation_heading"] = LANINS_001; - $var["stage_pre"] = LANINS_002; - $var["stage_num"] = LANINS_003; - $var["stage_title"] = LAN_ERROR; - $var["percent"] = 10; - $var["bartype"] = 'danger'; - $var['stage_content'] = "
    ".$error."
    "; - $var['debug_info'] = ''; - - $template = template_data(); - - foreach($var as $k=>$val) - { - $template = str_replace("{".$k."}", $val, $template); - - } - echo $template; - exit; -} - +important security checks and there is NO workaround. Please contact your host for more information."); +} + +//obsolete $installer_folder_name = 'e107_install'; +include_once("./{$HANDLERS_DIRECTORY}core_functions.php"); +include_once("./{$HANDLERS_DIRECTORY}e107_class.php"); + +function check_class($whatever='') +{ + return true; +} + +function getperms($arg, $ap = '') +{ + return true; +} + +$override = array(); + +if(isset($_POST['previous_steps'])) +{ + $tmp = unserialize(base64_decode($_POST['previous_steps'])); + $tmp = filter_var_array($tmp, FILTER_SANITIZE_STRING); + $override = (isset($tmp['paths']['hash'])) ? array('site_path'=>$tmp['paths']['hash']) : array(); + unset($tmp); +} + +//$e107_paths = compact('ADMIN_DIRECTORY', 'FILES_DIRECTORY', 'IMAGES_DIRECTORY', 'THEMES_DIRECTORY', 'PLUGINS_DIRECTORY', 'HANDLERS_DIRECTORY', 'LANGUAGES_DIRECTORY', 'HELP_DIRECTORY', 'CACHE_DIRECTORY', 'DOWNLOADS_DIRECTORY', 'UPLOADS_DIRECTORY', 'MEDIA_DIRECTORY', 'LOGS_DIRECTORY', 'SYSTEM_DIRECTORY', 'CORE_DIRECTORY'); +$e107_paths = array(); +$e107 = e107::getInstance(); +$ebase = realpath(dirname(__FILE__)); +if($e107->initInstall($e107_paths, $ebase, $override)===false) +{ + die_fatal_error("Error creating the following empty file: ".$ebase.DIRECTORY_SEPARATOR."e107_config.php
    Please create it manually and then run the installation again."); +} + +unset($e107_paths,$override,$ebase); + +// NEW - session handler +require_once(e_HANDLER.'session_handler.php'); +define('e_SECURITY_LEVEL', e_session::SECURITY_LEVEL_NONE); +define('e_COOKIE', 'e107install'); +e107::getSession(); // starts session, creates default namespace +// session_start(); + +function include_lan($path, $force = false) +{ + return include($path); +} +//obsolete $e107->e107_dirs['INSTALLER'] = "{$installer_folder_name}/"; + +if(isset($_GET['create_tables'])) +{ + create_tables_unattended(); + exit; +} + + + +$e_install = new e_install(); +$e_forms = new e_forms(); + +$e_install->template->SetTag("installer_css_http", $_SERVER['PHP_SELF']."?object=stylesheet"); +//obsolete $e_install->template->SetTag("installer_folder_http", e_HTTP.$installer_folder_name."/"); +$e_install->template->SetTag("files_dir_http", e_FILE_ABS); + +$e_install->renderPage(); + +/** + * Set Cookie + * @param string $name + * @param string $value + * @param integer $expire seconds + * @param string $path + * @param string $domain + * @param boolean $secure + * @return void + */ +function cookie($name, $value, $expire=0, $path = e_HTTP, $domain = '', $secure = 0) +{ + setcookie($name, $value, $expire, $path, $domain, $secure); +} + +class e_install +{ + var $paths; + var $template; + var $debug_info; + var $debug_db_info; + var $e107; + var $previous_steps; + var $stage; + var $post_data; + var $required = array(); //TODO - use for highlighting required fields with css/js. + var $logFile; // Name of log file, empty string if logging disabled + var $dbLink = NULL; // DB link - needed for PHP5.3 bug + var $session = null; + protected $pdo = false; + protected $debug = false; + + // public function __construct() + function __construct() + { + // notice removal, required from various core routines + define('USERID', 1); + define('USER', true); + define('ADMIN', true); + define('e_UC_MAINADMIN', 250); + define('E107_DEBUG_LEVEL',0); + + if($_SERVER['QUERY_STRING'] == "debug") + { + $this->debug = true; + } + + if(defined('PDO::ATTR_DRIVER_NAME')) + { + $this->pdo = true; + define('e_PDO', true); + } + + if(!empty($this->previous_steps['mysql']['prefix'])) + { + define('MPREFIX', $this->previous_steps['mysql']['prefix']); + } + + $tp = e107::getParser(); + + // session instance + $this->session = e107::getSession(); + + $this->logFile = ''; + if (MAKE_INSTALL_LOG) + { + if(is_writable(dirname(__FILE__))) + { + $this->logFile = dirname(__FILE__).'/e107InstallLog.log'; + } + } + // $this->logLine('Query string: '); + $this->template = new SimpleTemplate(); + while (@ob_end_clean()); + global $e107; + $this->e107 = $e107; + if(isset($_POST['previous_steps'])) + { + $this->previous_steps = unserialize(base64_decode($_POST['previous_steps'])); + $this->previous_steps = $tp->filter($this->previous_steps); + unset($_POST['previous_steps']); + } + else + { + $this->previous_steps = array(); + } + $this->get_lan_file(); + $this->post_data = $tp->filter($_POST); + + + + $this->template->SetTag('required', ''); + if(isset($this->previous_steps['language'])) + { + define("e_LANGUAGE", $this->previous_steps['language']); + include_lan(e_LANGUAGEDIR.e_LANGUAGE."/".e_LANGUAGE.".php"); + include_lan(e_LANGUAGEDIR.e_LANGUAGE."/admin/lan_admin.php"); + } + } + + /** + * Write a line of text to the log file (if enabled) - prepend time/date, append \n + * Can always call this routine - it will return if logging disabled + * + * @param string $logLine - text to log + * @return none + */ + protected function logLine($logLine) + { + if (!MAKE_INSTALL_LOG || ($this->logFile == '')) return; + $logfp = fopen($this->logFile, 'a+'); + fwrite($logfp, ($now = time()).', '.gmstrftime('%y-%m-%d %H:%M:%S',$now).' '.$logLine."\n"); + fclose($logfp); + } + + + + function add_button($id, $title='', $align = "right", $type = "submit") + { + + global $e_forms; + + $e_forms->form .= "
    "; + if($id != 'start') + { + // $this->form .= "« ".LAN_BACK." "; + $prevStage = ($this->stage - 1); + $e_forms->form .= " "; + } + if($id != 'back') + { + $e_forms->form .= ""; + } + $e_forms->form .= "
    \n"; + } + + function renderPage() + { + if(!isset($_POST['stage'])) + { + $_POST['stage'] = 1; + } + $_POST['stage'] = intval($_POST['stage']); + + if(!empty($_POST['back'])) + { + $_POST['stage'] = intval($_POST['back']); + } + + switch ($_POST['stage']) + { + case 1: + $this->stage_1(); + break; + case 2: + $this->stage_2(); + break; + case 3: + $this->stage_3(); + break; + case 4: + $this->stage_4(); + break; + case 5: + $this->stage_5(); + break; + case 6: + $this->stage_6(); + break; + case 7: + $this->stage_7(); + break; + case 8: + $this->stage_8(); + break; + default: + $this->raise_error("Install stage information from client makes no sense to me."); + } + + if($_SERVER['QUERY_STRING'] == "debug") + { + $this->template->SetTag("debug_info", print_a($this->previous_steps,TRUE)); + } + else + { + $this->template->SetTag("debug_info", (count($this->debug_info) ? print_a($this->debug_info,TRUE)."Backtrace:
    ".print_a($this,TRUE) : "")); + } + + echo $this->template->ParseTemplate(template_data(), TEMPLATE_TYPE_DATA); + } + + function raise_error($details) + { + $this->debug_info[] = array ( + 'info' => array ( + 'details' => $details, + 'backtrace' => debug_backtrace() + ) + ); + } + + function display_required() + { + if(empty($this->required)) + { + return; + } + $this->required = array_filter($this->required); + if(!empty($this->required)) + { + $this->template->SetTag("required","
    ". implode("
    ",$this->required)."
    "); + $this->required = array(); + } + } + + private function stage_1() + { + global $e_forms; + $this->stage = 1; + $this->logLine('Stage 1 started'); + + + + $this->template->SetTag("installation_heading", LANINS_001); + $this->template->SetTag("stage_pre", LANINS_002); + $this->template->SetTag("stage_num", LANINS_003); + $this->template->SetTag("stage_title", LANINS_004); + $this->template->SetTag("percent", 10); + $this->template->SetTag("bartype", 'warning'); + + $e_forms->start_form("language_select", $_SERVER['PHP_SELF'].($_SERVER['QUERY_STRING'] == "debug" ? "?debug" : "")); + $e_forms->add_select_item("language", $this->get_languages(), "English"); + $this->finish_form(); + $this->add_button("start", LAN_CONTINUE); + $output = " +
    +
    + +
    \n +
    \n +
    + ".$e_forms->return_form()." +

    +
    "; + $this->template->SetTag("stage_content", $output); + $this->logLine('Stage 1 completed'); + } + + private function stage_2() + { + global $e_forms; + $this->stage = 2; + $this->logLine('Stage 2 started'); + + if(!empty($_POST['language'])) + { + $this->previous_steps['language'] = $_POST['language']; + } + $this->template->SetTag("installation_heading", LANINS_001); + $this->template->SetTag("stage_pre", LANINS_002); + $this->template->SetTag("stage_num", LANINS_021); + $this->template->SetTag("stage_title", LANINS_022); + $this->template->SetTag("percent", 25); + $this->template->SetTag("bartype", 'warning'); + + if(!isset($this->previous_steps['mysql']['createdb'])) + { + $this->previous_steps['mysql']['createdb'] = 1; // default to yes. + } + + // $this->template->SetTag("onload", "document.getElementById('name').focus()"); + // $page_info = nl2br(LANINS_023); + $page_info = "
    ".LANINS_141."
    "; + $e_forms->start_form("versions", $_SERVER['PHP_SELF'].($_SERVER['QUERY_STRING'] == "debug" ? "?debug" : "")); + $isrequired = (($_SERVER['SERVER_ADDR'] == "127.0.0.1") || ($_SERVER['SERVER_ADDR'] == "localhost") || ($_SERVER['SERVER_ADDR'] == "::1") || preg_match('^192\.168\.\d{1,3}\.\d{1,3}$',$_SERVER['SERVER_ADDR'])) ? "" : "required='required'"; // Deals with IP V6, and 192.168.x.x address ranges, could be improved to validate x.x to a valid IP but for this use, I dont think its required to be that picky. + + $output = " +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + ".LANINS_030." +
    + + ".LANINS_031." +
    + + ".LANINS_032." +
    + + + ".LANINS_033." +
    + + ".LANINS_034." +
    +

    +
    + \n"; + + $e_forms->add_plain_html($output); + + + + $this->finish_form(); + $this->add_button("submit", LAN_CONTINUE); + $this->template->SetTag("stage_content", $page_info.$e_forms->return_form()); + $this->logLine('Stage 2 completed'); + } + + /** + * Replace hash paths and create folders if needed. + * + * @param none + * @return none + */ + private function updatePaths() + { + $hash = $this->e107->makeSiteHash($this->previous_steps['mysql']['db'],$this->previous_steps['mysql']['prefix']); + $this->e107->site_path = $hash; + + $this->previous_steps['paths']['hash'] = $hash; + + $omit = array('FILES_DIRECTORY','WEB_IMAGES_DIRECTORY'); + + foreach($this->e107->e107_dirs as $dir => $p) + { + if(in_array($dir, $omit)) { continue; } + + $this->e107->e107_dirs[$dir] = str_replace("[hash]", $hash, $this->e107->e107_dirs[$dir]); + + if(!is_dir($this->e107->e107_dirs[$dir])) + { + @mkdir($this->e107->e107_dirs[$dir]); + } + } + } + + private function stage_3() + { + + global $e_forms; + $success = TRUE; + $this->stage = 3; + $this->logLine('Stage 3 started'); + + $this->template->SetTag("installation_heading", LANINS_001); + $this->template->SetTag("stage_pre", LANINS_002); + $this->template->SetTag("stage_num", LANINS_036); + $this->template->SetTag("onload", "document.getElementById('name').focus()"); + $this->template->SetTag("percent", 40); + $this->template->SetTag("bartype", 'warning'); + $tp = e107::getParser(); + + if(!empty($_POST['server'])) + { + $this->previous_steps['mysql']['server'] = trim($tp->filter($_POST['server'])); + $this->previous_steps['mysql']['user'] = trim($tp->filter($_POST['name'])); + $this->previous_steps['mysql']['password'] = trim($tp->filter($_POST['password'])); + $this->previous_steps['mysql']['db'] = trim($tp->filter($_POST['db'])); + $this->previous_steps['mysql']['createdb'] = (isset($_POST['createdb']) && $_POST['createdb'] == true ? true : false); + $this->previous_steps['mysql']['prefix'] = trim($tp->filter($_POST['prefix'])); + } + + if(!empty($_POST['overwritedb'])) + { + $this->previous_steps['mysql']['overwritedb'] = 1; + } + + $success = $this->check_name($this->previous_steps['mysql']['db'], FALSE) && $this->check_name($this->previous_steps['mysql']['prefix'], TRUE); + + if ($success) + { + $success = $this->checkDbFields($this->previous_steps['mysql']); // Check for invalid characters + } + + if(!$success || $this->previous_steps['mysql']['server'] == "" || $this->previous_steps['mysql']['user'] == "") + { + $this->stage = 3; + $this->template->SetTag("stage_num", LANINS_021); + $e_forms->start_form("versions", $_SERVER['PHP_SELF'].($_SERVER['QUERY_STRING'] == "debug" ? "?debug" : "")); + $head = LANINS_039."

    \n"; + $output = " +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "; + + if (!$success) + { + $output .= ""; + } + + $output .= " +
    ".LANINS_030."
    ".LANINS_031."
    ".LANINS_032."
    +
    ".LANINS_033."
    ".LANINS_034."
    ".LANINS_105."
    +

    +
    + \n"; + $e_forms->add_plain_html($output); + $this->add_button("submit", LAN_CONTINUE); + $this->template->SetTag("stage_title", LANINS_040); + } + else + { + $this->template->SetTag("stage_title", LANINS_037.($this->previous_steps['mysql']['createdb'] == 1 ? LANINS_038 : "")); + + $sql = e107::getDb(); + if (!$res = $sql->connect($this->previous_steps['mysql']['server'], $this->previous_steps['mysql']['user'], $this->previous_steps['mysql']['password'])) + + // if (!$res = @mysql_connect($this->previous_steps['mysql']['server'], $this->previous_steps['mysql']['user'], $this->previous_steps['mysql']['password'])) + { + $success = FALSE; + $e_forms->start_form("versions", $_SERVER['PHP_SELF'].($_SERVER['QUERY_STRING'] == "debug" ? "?debug" : "")); + $page_content = LANINS_041.nl2br("\n\n".LANINS_083."\n".$sql->getLastErrorText().""); + + $alertType = 'error'; + } + elseif(($this->previous_steps['mysql']['createdb'] == 1) && empty($this->previous_steps['mysql']['overwritedb']) && $sql->database($this->previous_steps['mysql']['db'], $this->previous_steps['mysql']['prefix'])) + { + $success = false; + $e_forms->start_form("versions", $_SERVER['PHP_SELF'].($_SERVER['QUERY_STRING'] == "debug" ? "?debug" : "")); + $head = str_replace('[x]', ''.$this->previous_steps['mysql']['db'].'', "
    ". LANINS_127."
    "); + $alertType = 'error'; + $this->add_button('overwritedb', LANINS_128); + /* $e_forms->add_plain_html(" + " + + );*/ + + $this->finish_form(3); + $this->template->SetTag("stage_content", "
    ".$head."
    ".$e_forms->return_form()); + $this->logLine('Stage 3 completed'); + return; + } + else + { + $e_forms->start_form("versions", $_SERVER['PHP_SELF'].($_SERVER['QUERY_STRING'] == "debug" ? "?debug" : "")); + $page_content = " ".LANINS_042; + // @TODO Check database version here? +/* + $mysql_note = mysql_get_server_info(); + if (version_compare($mysql_note, MIN_MYSQL_VERSION, '>=')) + { + $success = FALSE; + + } +*/ + // Do brute force for now - Should be enough + + if(!empty($this->previous_steps['mysql']['overwritedb'])) + { + if($this->dbqry('DROP DATABASE `'.$this->previous_steps['mysql']['db'].'` ')) + { + $page_content .= "
    ".LANINS_136; + } + else + { + $success = false; + $page_content .= "

    ".LANINS_043.nl2br("\n\n".LANINS_083."\n".e107::getDb()->getLastErrorText().""); + } + + } + + if($this->previous_steps['mysql']['createdb'] == 1) + { + $notification = "
    ".LANINS_044; + $query = 'CREATE DATABASE `'.$this->previous_steps['mysql']['db'].'` CHARACTER SET `utf8` '; + + } + else + { + $notification = "
    ".LANINS_137; + $query = 'ALTER DATABASE `'.$this->previous_steps['mysql']['db'].'` CHARACTER SET `utf8` '; + } + + if (!$this->dbqry($query)) + { + $success = false; + $alertType = 'error'; + $page_content .= "

    "; + $page_content .= (empty($this->previous_steps['mysql']['createdb'])) ? LANINS_129 : LANINS_043; + + + $page_content .= nl2br("\n\n".LANINS_083."\n".e107::getDb()->getLastErrorText().""); + } + else + { + $this->dbqry('SET NAMES `utf8`'); + + $page_content .= $notification; // " + } + } + + if($success) + { + + // $page_content .= "

    ".LANINS_045."

    "; + $this->add_button("submit", LAN_CONTINUE); + $alertType = 'success'; + } + else + { + $this->add_button("back", LAN_CONTINUE); + } + $head = $page_content; + } + if ($success) + $this->finish_form(); + else + { + $this->finish_form(3); + } + $this->template->SetTag("stage_content", "
    ".$head."
    ".$e_forms->return_form()); + $this->logLine('Stage 3 completed'); + } + + private function stage_4() + { + global $e_forms; + + $this->stage = 4; + $this->logLine('Stage 4 started'); + + $this->template->SetTag("installation_heading", LANINS_001); + $this->template->SetTag("stage_pre", LANINS_002); + $this->template->SetTag("stage_num", LANINS_007); + $this->template->SetTag("stage_title", LANINS_008); + $this->template->SetTag("percent", 50); + $this->template->SetTag("bartype", 'warning'); + $not_writable = $this->check_writable_perms('must_write'); // Some directories MUST be writable + $opt_writable = $this->check_writable_perms('can_write'); // Some directories CAN optionally be writable + $version_fail = false; + $perms_errors = ""; + $mysql_pass = false; + + if(count($not_writable)) + { + $perms_pass = false; + foreach ($not_writable as $file) + { + $perms_errors .= (substr($file, -1) == "/" ? LANINS_010a : LANINS_010)."
    {$file}
    \n"; + } + $perms_notes = LANINS_018; + } + elseif (count($opt_writable)) + { + $perms_pass = true; + foreach ($opt_writable as $file) + { + $perms_errors .= (substr($file, -1) == "/" ? LANINS_010a : LANINS_010)."
    {$file}
    \n"; + } + $perms_notes = LANINS_106; + } + elseif (filesize('e107_config.php') > 1) + { // Must start from an empty e107_config.php + $perms_pass = FALSE; + $perms_errors = LANINS_121; + $perms_notes = " ".LANINS_122; + } + else + { + $perms_pass = true; + $perms_errors = " "; + $perms_notes = " ".LANINS_017; + } + + if(!function_exists("mysql_connect") && !defined('PDO::ATTR_DRIVER_NAME')) + { + $version_fail = true; + $mysql_note = LAN_ERROR; + $mysql_help = LANINS_012; + } + elseif (!e107::getDb()->connect($this->previous_steps['mysql']['server'], $this->previous_steps['mysql']['user'], $this->previous_steps['mysql']['password'])) +// elseif (!@mysql_connect($this->previous_steps['mysql']['server'], $this->previous_steps['mysql']['user'], $this->previous_steps['mysql']['password'])) + { + $mysql_note = LAN_ERROR; + $mysql_help = LANINS_013; + } + else + { + // $mysql_note = mysql_get_server_info(); + $mysql_note = e107::getDb()->getServerInfo(); + + if($this->pdo == true) + { + $mysql_note .= " (PDO)"; + } + + if (version_compare($mysql_note, MIN_MYSQL_VERSION, '>=')) + { + $mysql_help = " ".LANINS_017; + $mysql_pass = true; + } + else + { + $mysql_help = " ".LANINS_105; + } + } + + $php_version = phpversion(); + + if(version_compare($php_version, MIN_PHP_VERSION, ">=")) + { + $php_help = " ".LANINS_017; + } + else + { + $php_help = " ".LANINS_019; + } + + + + $e_forms->start_form("versions", $_SERVER['PHP_SELF'].($_SERVER['QUERY_STRING'] == "debug" ? "?debug" : "")); + + + + $permColor = ($perms_pass == true) ? "text-success" : "text-danger"; + $PHPColor = ($version_fail == false) ? "text-success" : "text-danger"; + $mysqlColor = ($mysql_pass == true) ? "text-success" : "text-danger"; +/* + if(version_compare($php_version, 7.1, ">=")) // XXX Remove once tested thoroughly + { + $php_help = " PHP 7.1 may have issues with e107. We recommend using 7.0.x versions instead until further testing has been performed."; + $PHPColor = 'text-warning'; + } +*/ + + $extensionCheck = array( + 'pdo' => array('label'=> "PDO (MySQL)", 'status' => extension_loaded('pdo_mysql'), 'url'=> ''), + 'xml' => array('label'=> LANINS_050, 'status' => function_exists('utf8_encode') && class_exists('DOMDocument', false), 'url'=> 'http://php.net/manual/en/ref.xml.php'), + 'exif' => array('label'=> LANINS_048, 'status' => function_exists('exif_imagetype'), 'url'=> 'http://php.net/manual/en/book.exif.php'), + 'curl' => array('label'=> 'Curl Library', 'status' => function_exists('curl_version'), 'url'=> 'http://php.net/manual/en/book.curl.php'), + 'gd' => array('label'=> 'GD Library', 'status' => function_exists('gd_info'), 'url'=> 'http://php.net/manual/en/book.image.php'), + 'mb' => array('label'=> 'MB String Library', 'status' => function_exists('mb_strimwidth'), 'url'=> 'http://php.net/manual/en/book.mbstring.php'), + ); + + + + $output = " + + + + + + + + + + + + + + + + + + "; + + foreach($extensionCheck as $ext) + { + $statusText = ($ext['status'] === true) ? LANINS_051 : LANINS_052; + $statusColor = ($ext['status'] === true) ? "text-success" : "text-error"; + $statusIcon = ($ext['status'] === true) ? " ".LANINS_017 : str_replace(array("[x]",'[y]'), array($ext['label'], "php.net"), LANINS_145); + + $output .= " + + + + + "; + } + + + $output .= " +
    ".LANINS_014."{$perms_errors}{$perms_notes}
    ".LANINS_015."{$php_version}{$php_help}
    MySQL{$mysql_note}{$mysql_help}
    ".$ext['label']."".$statusText."".$statusIcon."
    \n"; + + if(!$perms_pass || (($extensionCheck['xml']['status'] !== true))) + { + $this->add_button("retest_perms", LANINS_009); + $this->stage = 3; // make the installer jump back a step + } + elseif ($perms_pass && !$version_fail && ($extensionCheck['xml']['status'] == true)) + { + $this->add_button("continue_install", LAN_CONTINUE); + } + + $this->finish_form(); + $this->template->SetTag("stage_content", $output.$e_forms->return_form()); + $this->logLine('Stage 4 completed'); + } + + /** + * Install stage 5 - collect Admin Login Data. + * + * @return string HTML form of stage 5. + */ + private function stage_5() + { + global $e_forms; + + $this->updatePaths(); // update dynamic paths and create media and system directories - requires mysql info. + + $this->stage = 5; + $this->logLine('Stage 5 started'); + + $this->display_required(); + $this->template->SetTag("installation_heading", LANINS_001); + $this->template->SetTag("stage_pre", LANINS_002); + $this->template->SetTag("stage_num", LANINS_046); + $this->template->SetTag("stage_title", defset('LANINS_147', 'Administration')); + // $this->template->SetTag("onload", "document.getElementById('u_name').focus()"); + $this->template->SetTag("percent", 60); + $this->template->SetTag("bartype", 'warning'); + + $e_forms->start_form("admin_info", $_SERVER['PHP_SELF'].($_SERVER['QUERY_STRING'] == "debug" ? "?debug" : "")); + $output = " +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + previous_steps['admin']['user'] : "")."' maxlength='60' /> + ".LANINS_073." +
    + previous_steps['admin']['display'] : "")."' maxlength='60' /> + ".LANINS_123." +
    + + ".LANINS_124." +
    + + ".LANINS_079." +
    + previous_steps['admin']['email'] : '')."' maxlength='100' /> + ".LANINS_081." +
    + + + + + + + + + + +
    "; + + $d = $this->get_theme_xml('bootstrap3'); + $opts = array(); + + foreach($d['css'] as $val) + { + $key = $val['name']; + + if(empty($val['thumbnail'])) + { + continue; + } + + $opts[$key] = array ( + 'title' => $val['info'], + 'preview' => e_THEME."bootstrap3/".$val['thumbnail'], + 'description' =>'', + 'category'=>'' + ); + + + } + + $output .= $this->thumbnailSelector('admincss', $opts, 'css/bootstrap-dark.min.css'); + + $output .= " + + +
    +

    +
    + \n"; + $e_forms->add_plain_html($output); + $this->finish_form(); + $this->add_button("submit", LAN_CONTINUE); + $this->template->SetTag("stage_content", $e_forms->return_form()); + $this->logLine('Stage 5 completed'); + } + + /** + * Collect User's Website Preferences + * + * @return string HTML form of stage 6. + */ + private function stage_6() + { + global $e_forms; + $tp = e107::getParser(); + $this->stage = 6; + $this->logLine('Stage 6 started'); + + // -------------------- Save Step 5 Data ------------------------- + if(!vartrue($this->previous_steps['admin']['user']) || varset($_POST['u_name'])) + { + $_POST['u_name'] = str_replace(array("'", '"'), "", $_POST['u_name']); + $this->previous_steps['admin']['user'] = $tp->filter($_POST['u_name']); + } + + if(!vartrue($this->previous_steps['admin']['display']) || varset($_POST['d_name'])) + { + $_POST['d_name'] = str_replace(array("'", '"'), "", $_POST['d_name']); + if ($_POST['d_name'] == "") + { + $this->previous_steps['admin']['display'] = $tp->filter($_POST['u_name']); + } + else + { + $this->previous_steps['admin']['display'] = $tp->filter($_POST['d_name']); + } + } + + if(!vartrue($this->previous_steps['admin']['email']) || varset($_POST['email'])) + { + $this->previous_steps['admin']['email'] = $tp->filter($_POST['email'],'email'); + } + + if(varset($_POST['pass1']) || !vartrue($this->previous_steps['admin']['password'])) + { + if($_POST['pass1'] != $_POST['pass2']) + { + $this->required['pass1'] = LANINS_049; // passwords don't match. + } + elseif(!vartrue($_POST['pass1'])) + { + $this->required['pass1'] = LANINS_077; + } + else + { + $this->previous_steps['admin']['password'] = $_POST['pass1']; + } + } + + if(!empty($_POST['admincss'])) + { + $this->previous_steps['prefs']['admincss'] = $tp->filter($_POST['admincss']); + } + else // empty + { + $this->previous_steps['prefs']['admincss'] = 'css/bootstrap-dark.min.css'; + } + + // ------------- Validate Step 5 Data. -------------------------- + if(!vartrue($this->previous_steps['admin']['user']) || !vartrue($this->previous_steps['admin']['password'])) + { + $this->required['u_name'] = LANINS_086; // + } + + if(!empty($this->required['u_name']) || !empty($this->required['pass1'])) + { + return $this->stage_5(); + } + + // required for various core routines + if(!defined('USERNAME')) + { + define('USERNAME', $this->previous_steps['admin']['user']); + define('USEREMAIL', $this->previous_steps['admin']['email']); + } + + // ------------- Step 6 Form -------------------------------- + $this->display_required(); + $this->template->SetTag("installation_heading", LANINS_001); + $this->template->SetTag("stage_pre", LANINS_002); + $this->template->SetTag("stage_num", LANINS_056); + $this->template->SetTag("stage_title", LANINS_117); // Website Preferences; + // $this->template->SetTag("onload", "document.getElementById('sitename').focus()"); + $this->template->SetTag("percent", 70); + $this->template->SetTag("bartype", 'warning'); + + $e_forms->start_form("pref_info", $_SERVER['PHP_SELF'].($_SERVER['QUERY_STRING'] == "debug" ? "?debug" : "")); + $output = " +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + "; + + $themes = $this->get_themes(); + + $opts = array(); + + foreach($themes as $val) + { + + /*if($val != 'bootstrap3' && $val != 'voux') + { + continue; + }*/ + + + + $themeInfo = $this->get_theme_xml($val); + + + $opts[$val] = array( + 'title' =>vartrue($themeInfo['@attributes']['name']), + 'category' => vartrue($themeInfo['category']), + 'preview' => e_THEME.$val."/".$themeInfo['thumbnail'], + 'description' => vartrue($themeInfo['info']) + ); + + /* $title = vartrue($themeInfo['@attributes']['name']); + $category = vartrue($themeInfo['category']); + $preview = e_THEME.$val."/".$themeInfo['thumbnail']; + $description = vartrue($themeInfo['info']); + + if(!is_readable($preview)) + { + continue; + } + + + $thumbnail = "".$val.""; + + + $selected = ($val === DEFAULT_INSTALL_THEME) ? " checked" : ""; + + $output .= " +
    + +
    ";*/ + } + + $output .= $this->thumbnailSelector('sitetheme', $opts, DEFAULT_INSTALL_THEME); + + + $output .= " + +
    + + ".LANINS_119." +
    + + ".LANINS_112." +
    +

    +
    + \n"; + $e_forms->add_plain_html($output); + $this->finish_form(); + $this->add_button("submit", LAN_CONTINUE); + $this->template->SetTag("stage_content", $e_forms->return_form()); + $this->logLine('Stage 6 completed'); + } + + + private function thumbnailSelector($name, $opts, $default='') + { + + $ret = ''; + + foreach($opts as $key=>$val) + { + + if(!is_readable($val['preview']) || !is_file($val['preview'])) + { + continue; + } + + + $thumbnail = "".$key.""; + + + $selected = ($key === $default) ? " checked" : ""; + + $categoryInfo = !empty($val['category']) ? "(".$val['category'].")" : ""; + + $ret .= " +
    + +
    "; + } + + + return $ret; + + } + + private function stage_7() + { + global $e_forms; + $tp = e107::getParser(); + + $this->e107->e107_dirs['SYSTEM_DIRECTORY'] = str_replace("[hash]",$this->e107->site_path,$this->e107->e107_dirs['SYSTEM_DIRECTORY']); + $this->e107->e107_dirs['CACHE_DIRECTORY'] = str_replace("[hash]",$this->e107->site_path,$this->e107->e107_dirs['CACHE_DIRECTORY']); + $this->e107->e107_dirs['SYSTEM_DIRECTORY'] = str_replace("/".$this->e107->site_path,"",$this->e107->e107_dirs['SYSTEM_DIRECTORY']); + $this->e107->e107_dirs['MEDIA_DIRECTORY'] = str_replace("/".$this->e107->site_path,"",$this->e107->e107_dirs['MEDIA_DIRECTORY']); + + $this->stage = 7; + $this->logLine('Stage 7 started'); + + // required for various core routines + if(!defined('USERNAME')) + { + define('USERNAME', $this->previous_steps['admin']['user']); + define('USEREMAIL', $this->previous_steps['admin']['email']); + } + + if(varset($_POST['sitename'])) + { + $this->previous_steps['prefs']['sitename'] = $tp->filter($_POST['sitename']); + } + + if(varset($_POST['sitetheme'])) + { + $this->previous_steps['prefs']['sitetheme'] = $tp->filter($_POST['sitetheme']); + } + + if(varset($_POST['generate_content'])) + { + $this->previous_steps['generate_content'] = $tp->filter($_POST['generate_content'],'int'); + } + + if(varset($_POST['install_plugins'])) + { + $this->previous_steps['install_plugins'] = $tp->filter($_POST['install_plugins'],'int'); + } + + // Validate + if(!vartrue($this->previous_steps['prefs']['sitename'])) + { + $this->required['sitename'] = LANINS_113; // 'Please enter a website name.'; // should be used to highlight the required field. (using css for example) + } + if(!vartrue($this->previous_steps['prefs']['sitetheme'])) + { + $this->required['sitetheme'] = LANINS_114; // 'Please select a theme.'; + } + + if(!empty($this->required['sitetheme']) || !empty($this->required['sitename'])) + { + return $this->stage_6(); + } + + $config_file = "previous_steps['mysql']['server']}'; +\$mySQLuser = '{$this->previous_steps['mysql']['user']}'; +\$mySQLpassword = '{$this->previous_steps['mysql']['password']}'; +\$mySQLdefaultdb = '{$this->previous_steps['mysql']['db']}'; +\$mySQLprefix = '{$this->previous_steps['mysql']['prefix']}'; +\$mySQLcharset = 'utf8'; + +\$ADMIN_DIRECTORY = '{$this->e107->e107_dirs['ADMIN_DIRECTORY']}'; +\$FILES_DIRECTORY = '{$this->e107->e107_dirs['FILES_DIRECTORY']}'; +\$IMAGES_DIRECTORY = '{$this->e107->e107_dirs['IMAGES_DIRECTORY']}'; +\$THEMES_DIRECTORY = '{$this->e107->e107_dirs['THEMES_DIRECTORY']}'; +\$PLUGINS_DIRECTORY = '{$this->e107->e107_dirs['PLUGINS_DIRECTORY']}'; +\$HANDLERS_DIRECTORY = '{$this->e107->e107_dirs['HANDLERS_DIRECTORY']}'; +\$LANGUAGES_DIRECTORY = '{$this->e107->e107_dirs['LANGUAGES_DIRECTORY']}'; +\$HELP_DIRECTORY = '{$this->e107->e107_dirs['HELP_DIRECTORY']}'; +\$MEDIA_DIRECTORY = '{$this->e107->e107_dirs['MEDIA_DIRECTORY']}'; +\$SYSTEM_DIRECTORY = '{$this->e107->e107_dirs['SYSTEM_DIRECTORY']}'; + + +// -- Optional -- +// define('e_DEBUG', true); // Enable debug mode to allow displaying of errors +// define('e_HTTP_STATIC', 'https://static.mydomain.com/'); // Use a static subdomain for js/css/images etc. +// define('e_MOD_REWRITE_STATIC', true); // Rewrite static image urls. +// define('e_LOG_CRITICAL', true); // log critical errors but do not display them to user. +// define('e_GIT', 'path-to-git'); // Path to GIT for developers +// define('X-FRAME-SAMEORIGIN', false); // Option to override X-Frame-Options +// define('e_PDO, true); // Enable PDO mode (used in PHP > 7 and when mysql_* methods are not available) + +"; +/* +if($this->pdo == true) +{ + $config_file .= 'define("e_PDO", true);'; + $config_file .= "\n\n"; +}*/ + + + $config_result = $this->write_config($config_file); + + if ($config_result) + { + $page = $config_result."
    "; + $this->logLine('Error writing config file: '.$config_result); + $alertType = 'warning'; + } else { + $this->logLine('Config file written successfully'); + } + + + // Data is okay - Continue. + + // $this->previous_steps['prefs']['sitename'] = $_POST['sitename']; + // $this->previous_steps['prefs']['sitetheme'] = $_POST['sitetheme']; + // $this->previous_steps['generate_content'] = $_POST['generate_content']; + + $this->template->SetTag("installation_heading", LANINS_001); + $this->template->SetTag("stage_pre", LANINS_002); + $this->template->SetTag("stage_num", LANINS_058); + $this->template->SetTag("stage_title", LANINS_055); + $this->template->SetTag("percent", 80); + $this->template->SetTag("bartype", 'warning'); + + $e_forms->start_form("confirmation", $_SERVER['PHP_SELF'].($_SERVER['QUERY_STRING'] == "debug" ? "?debug" : "")); + $page = '
    '.nl2br(LANINS_057).'
    '; + $this->finish_form(); + $this->add_button("submit", LAN_CONTINUE); + + + + $this->template->SetTag("stage_content", $page.$e_forms->return_form()); + $this->logLine('Stage 7 completed'); + + } + + /** + * Stage 8 - actually create database and set up the site + * + * @return none + */ + private function stage_8() + { + global $e_forms; + + //$system_dir = str_replace("/".$this->e107->site_path,"",$this->e107->e107_dirs['SYSTEM_DIRECTORY']); + //$media_dir = str_replace("/".$this->e107->site_path,"",$this->e107->e107_dirs['MEDIA_DIRECTORY']); + + // required for various core routines + if(!defined('USERNAME')) + { + define('USERNAME', $this->previous_steps['admin']['user']); + define('USEREMAIL', $this->previous_steps['admin']['email']); + } + + $this->stage = 8; + $this->logLine('Stage 8 started'); + + $this->template->SetTag("installation_heading", LANINS_001); + $this->template->SetTag("stage_pre", LANINS_002); + $this->template->SetTag("stage_num", LANINS_120); + $this->template->SetTag("stage_title", LANINS_071); + $this->template->SetTag("percent", 100); + $this->template->SetTag("bartype", 'success'); + + $htaccessError = $this->htaccess(); + $this->saveFileTypes(); + + $e_forms->start_form("confirmation", "index.php"); + + $errors = $this->create_tables(); + if ($errors == true) + { + $this->logLine('Errors creating tables: '.$errors); + $page = $errors."
    "; + $alertType = 'error'; + } + else + { + $alertType = 'success'; + $this->logLine('Tables created successfully'); + $this->import_configuration(); + $page = nl2br(LANINS_125)."
    "; + $page .= (is_writable('e107_config.php')) ? "
    ".str_replace("e107_config.php","e107_config.php",LANINS_126) : ""; + + if($htaccessError) + { + $page .= "
    ".$htaccessError; + } + $this->add_button('submit', LAN_CONTINUE); + } + + $this->finish_form(); + $this->stats(); + $this->template->SetTag("stage_content", "
    ".$page."
    ".$e_forms->return_form()); + $this->logLine('Stage 8 completed'); + + e107::getMessage()->reset(false, false, true); + } + + private function saveFileTypes() + { + $data = ' + + +'; + + return file_put_contents($this->e107->e107_dirs['SYSTEM_DIRECTORY']."filetypes.xml",$data); + + } + + + + protected function stats() + { + global $e_forms; + + $data = array('name'=>$this->previous_steps['prefs']['sitename'], 'theme'=>$this->previous_steps['prefs']['sitetheme'], 'language'=>$this->previous_steps['language'], 'url'=>$_SERVER['HTTP_REFERER']);; + $base = base64_encode(http_build_query($data, null, '&')); + $url = "https://e107.org/e-install/".$base; + $e_forms->add_plain_html(""); + + } + + + + /** + * htaccess - handle the .htaccess file + * + * @return string $error + */ + protected function htaccess() + { + $error = ""; + + if(!file_exists(".htaccess")) + { + if(!rename("e107.htaccess",".htaccess")) + { + $error = LANINS_142; + } + elseif($_SERVER['QUERY_STRING'] == "debug") + { + rename(".htaccess","e107.htaccess"); + $error = "DEBUG: Rename from e107.htaccess to .htaccess was successful"; + } + } + elseif(file_exists("e107.htaccess")) + { + $srch = array('[b]','[/b]'); + $repl = array('',''); + $error = str_replace($srch,$repl, LANINS_144); // too early to use e107::getParser() so use str_replace(); + } + return $error; + } + + /** + * Import and generate preferences and default content. + * + * @return boolean + */ + //FIXME always return FALSE??? + public function import_configuration() + { + $this->logLine('Starting configuration import'); + + // PRE-CONFIG start - create and register blank config instances - do not load! + $config_aliases = array( + 'core', + 'core_backup', + 'emote', + 'menu', + 'search', + 'notify', + ); + foreach ($config_aliases as $alias) + { + e107::getConfig($alias, false)->clearPrefCache(); + } + // PRE-CONFIG end + + // Basic stuff to get the handlers/classes to work. + + + // $udirs = "admin/|plugins/|temp"; + // $e_SELF = $_SERVER['PHP_SELF']; + // $e_HTTP = preg_replace("#".$udirs."#i", "", substr($e_SELF, 0, strrpos($e_SELF, "/"))."/"); + + // define("MAGIC_QUOTES_GPC", (ini_get('magic_quotes_gpc') ? true : false)); + // define('CHARSET', 'utf-8'); + // define("e_LANGUAGE", $this->previous_steps['language']); + // define('e_SELF', 'http://'.$_SERVER['HTTP_HOST']) . ($_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_FILENAME']); + + $themeImportFile = array(); + $themeImportFile[0] = $this->e107->e107_dirs['THEMES_DIRECTORY'].$this->previous_steps['prefs']['sitetheme']."/install.xml"; + $themeImportFile[1] = $this->e107->e107_dirs['THEMES_DIRECTORY'].$this->previous_steps['prefs']['sitetheme']."/install/install.xml"; + // $themeImportFile[3] = $this->e107->e107_dirs['CORE_DIRECTORY']. "xml/default_install.xml"; + + $XMLImportfile = false; + + if(vartrue($this->previous_steps['generate_content'])) + { + foreach($themeImportFile as $file) + { + if(is_readable($file)) + { + $XMLImportfile = $file; + break; + } + } + } + + $tp = e107::getParser(); + + define('PREVIEWTHEMENAME',""); // Notice Removal. + +// include_lan($this->e107->e107_dirs['LANGUAGES_DIRECTORY'].$this->previous_steps['language']."/lan_prefs.php"); + include_lan($this->e107->e107_dirs['LANGUAGES_DIRECTORY'].$this->previous_steps['language']."/admin/lan_theme.php"); + + // [SecretR] should work now - fixed log errors (argument noLogs = true) change to false to enable log + + $coreConfig = $this->e107->e107_dirs['CORE_DIRECTORY']. "xml/default_install.xml"; + $ret = e107::getXml()->e107Import($coreConfig, 'replace', true, false); // Add core pref values + $this->logLine('Attempting to Write Core Prefs.'); + $this->logLine(print_r($ret, true)); + /* + if($XMLImportfile) // We cannot rely on themes to include all prefs..so use 'replace'. + { + $ret2 = e107::getXml()->e107Import($XMLImportfile, 'replace', true, false); // Overwrite specific core pref and tables entries. + $this->logLine('Attempting to write Theme Prefs/Tables (install.xml)'); + $this->logLine(print_r($ret2, true)); + } + + */ //Create default plugin-table entries. + // e107::getConfig('core')->clearPrefCache(); + e107::getPlugin()->update_plugins_table('update'); + $this->logLine('Plugins table updated'); + + // Install Theme-required plugins + if(vartrue($this->previous_steps['install_plugins'])) + { + if($themeInfo = $this->get_theme_xml($this->previous_steps['prefs']['sitetheme'])) + { + if(isset($themeInfo['plugins']['plugin'])) + { + foreach($themeInfo['plugins']['plugin'] as $k=>$plug) + { + $this->install_plugin($plug['@attributes']['name']); + $this->logLine('Theme-related plugin installed: '.$plug['@attributes']['name']); + } + } + } + } + + + + e107::getSingleton('e107plugin')->save_addon_prefs('update'); // save plugin addon pref-lists. eg. e_latest_list. + $this->logLine('Addon prefs saved'); + + // do this AFTER any required plugins are installated. + if($XMLImportfile) // We cannot rely on themes to include all prefs..so use 'replace'. + { + $ret2 = e107::getXml()->e107Import($XMLImportfile, 'replace', true, false); // Overwrite specific core pref and tables entries. + $this->logLine('Attempting to write Theme Prefs/Tables (install.xml)'); + $this->logLine(print_r($ret2, true)); + } + + + $tm = e107::getSingleton('themeHandler'); + $tm->noLog = true; // false to enable log + $tm->setTheme($this->previous_steps['prefs']['sitetheme'], false); + + // Admin log fix - don't allow logs to be called inside pref handler + // FIX + e107::getConfig('core')->setParam('nologs', true); // change to false to enable log + $pref = e107::getConfig('core')->getPref(); + + // Set Preferences defined during install - overwriting those that may exist in the XML. + + $this->previous_steps['prefs']['sitelanguage'] = $this->previous_steps['language']; + $this->previous_steps['prefs']['sitelang_init'] = $this->previous_steps['language']; + + $this->previous_steps['prefs']['siteadmin'] = $this->previous_steps['admin']['display']; + $this->previous_steps['prefs']['siteadminemail'] = $this->previous_steps['admin']['email']; + $this->previous_steps['prefs']['install_date'] = time(); + $this->previous_steps['prefs']['siteurl'] = e_HTTP; + + $this->previous_steps['prefs']['sitetag'] = "e107 Website System"; + $this->previous_steps['prefs']['sitedisclaimer'] = ''; + + $this->previous_steps['prefs']['replyto_name'] = $this->previous_steps['admin']['display']; + $this->previous_steps['prefs']['replyto_email'] = $this->previous_steps['admin']['email']; + + // Cookie name fix, ended up with 406 error when non-latin words used + $cookiename = preg_replace('/[^a-z0-9]/i', '', trim($this->previous_steps['prefs']['sitename'])); + $this->previous_steps['prefs']['cookie_name'] = ($cookiename ? substr($cookiename, 0, 4).'_' : 'e_').'cookie'; + + ### URL related prefs + // set all prefs so that they are available, required for adminReadModules() - it checks which plugins are installed + e107::getConfig('core')->setPref($this->previous_steps['prefs']); + + $url_modules = eRouter::adminReadModules(); + $url_locations = eRouter::adminBuildLocations($url_modules); + $url_config = eRouter::adminBuildConfig(array(), $url_modules); + + $this->previous_steps['prefs']['url_aliases'] = array(); + $this->previous_steps['prefs']['url_config'] = $url_config; + $this->previous_steps['prefs']['url_modules'] = $url_modules; + $this->previous_steps['prefs']['url_locations'] = $url_locations; + eRouter::clearCache(); + $this->logLine('Core URL config set to default state'); + + $us = e107::getUserSession(); + + if($us->passwordAPIExists() === true) + { + $this->previous_steps['prefs']['passwordEncoding'] = PASSWORD_E107_PHP; + $pwdEncoding = PASSWORD_E107_PHP; + } + else + { + $pwdEncoding = PASSWORD_E107_MD5; // default already in default_install.xml + } + + // Set prefs, save + e107::getConfig('core')->setPref($this->previous_steps['prefs']); + e107::getConfig('core')->save(FALSE,TRUE, FALSE); // save preferences made during install. + $this->logLine('Core prefs set to install choices'); + + // Create the admin user - replacing any that may be been included in the XML. + + $hash = $us->HashPassword($this->previous_steps['admin']['password'],$this->previous_steps['admin']['user'], $pwdEncoding); + + $ip = $_SERVER['REMOTE_ADDR']; + $userp = "1, '{$this->previous_steps['admin']['display']}', '{$this->previous_steps['admin']['user']}', '', '".$hash."', '', '{$this->previous_steps['admin']['email']}', '', '', 0, ".time().", 0, 0, 0, 0, 0, '{$ip}', 0, '', 0, 1, '', '', '0', '', ".time().", ''"; + $qry = "REPLACE INTO {$this->previous_steps['mysql']['prefix']}user VALUES ({$userp})"; + $this->dbqry("REPLACE INTO {$this->previous_steps['mysql']['prefix']}user VALUES ({$userp})" ); + $this->logLine('Admin user created'); + + // Add Default user-extended values; + $extendedQuery = "REPLACE INTO `{$this->previous_steps['mysql']['prefix']}user_extended` (`user_extended_id` , `user_hidden_fields`) VALUES ('1', NULL );"; + $this->dbqry($extendedQuery); + + e107::getDb()->close(); + // mysql_close($this->dbLink); + + e107::getMessage()->reset(false, false, true); + + return false; + } + + /** + * Install a Theme required plugin. + * + * @param string $plugpath - plugin folder name + * @return void + */ + public function install_plugin($plugpath) //FIXME - requires default plugin table entries, see above. + { + e107::getDb()->gen("SELECT * FROM #plugin WHERE plugin_path = '".$plugpath."' LIMIT 1"); + $row = e107::getDb()->fetch(); + e107::getPlugin()->install_plugin($row['plugin_id']); + + e107::getMessage()->reset(false, false, true); + + return; + } + + /** + * Check a DB name or table prefix - anything starting with a numeric followed by 'e' causes problems. + * Return TRUE if acceptable, FALSE if unacceptable + * Empty string returns the value of $blank_ok (caller should set TRUE for prefix, FALSE for DB name) + * + * @param string $str + * @param boolean $blank_ok [optional] + * @return boolean + */ + function check_name($str, $blank_ok = FALSE) + { + if ($str == '') + return $blank_ok; + if (preg_match("#^\d+[e|E]#", $str)) + return FALSE; + return TRUE; + } + + /** + * checkDbFields - Check an array of db-related fields for illegal characters + * + * @param array $fields + * @return boolean TRUE for OK, FALSE for invalid character + */ + function checkDbFields($fields) + { + if (!is_array($fields)) return FALSE; + foreach (array('server', 'user', 'db', 'prefix') as $key) + { + if (isset($fields[$key])) + { + if (strtr($fields[$key],"';", ' ') != $fields[$key]) + { + return FALSE; // Invalid character found + } + } + } + return TRUE; + } + + function get_lan_file() + { + if(!empty($_POST['language'])) + { + $this->previous_steps['language'] = $_POST['language']; + } + + if(!isset($this->previous_steps['language'])) + { + $this->previous_steps['language'] = "English"; + } + + include_lan($this->e107->e107_dirs['LANGUAGES_DIRECTORY'].$this->previous_steps['language']."/lan_installer.php"); + // $this->lan_file = "{$this->e107->e107_dirs['LANGUAGES_DIRECTORY']}{$this->previous_steps['language']}/lan_installer.php"; + // if(is_readable($this->lan_file)) + // { + // include($this->lan_file); + // } + // elseif(is_readable("{$this->e107->e107_dirs['LANGUAGES_DIRECTORY']}English/lan_installer.php")) + // { + // include("{$this->e107->e107_dirs['LANGUAGES_DIRECTORY']}English/lan_installer.php"); + // } + // else + // { + // $this->raise_error("Fatal: Could not get valid language file for installation."); + // } + } + + /** + * get_languages - check language folder for language names + * + * @param none + * @return array $lanlist + */ + function get_languages() + { + $handle = opendir($this->e107->e107_dirs['LANGUAGES_DIRECTORY']); + $lanlist = array(); + while ($file = readdir($handle)) + { + if ($file != "." && $file != ".." && $file != "/" && $file != "CVS" && $file != 'index.html') + { + if(file_exists("./{$this->e107->e107_dirs['LANGUAGES_DIRECTORY']}{$file}/lan_installer.php")) + { + $lanlist[] = $file; + } + } + } + closedir($handle); + return $lanlist; + } + + /** + * get_themes - check theme folder for theme names + * + * @param none + * @return array $themelist + */ + function get_themes() + { + $handle = opendir($this->e107->e107_dirs['THEMES_DIRECTORY']); + $themelist = array(); + while ($file = readdir($handle)) + { + if (is_dir($this->e107->e107_dirs['THEMES_DIRECTORY'].$file) && $file !='_blank') + { + if(is_readable("./{$this->e107->e107_dirs['THEMES_DIRECTORY']}{$file}/theme.xml")) + { + $themelist[] = $file; + } + } + } + closedir($handle); + return $themelist; + } + + /** + * get_theme_xml - check theme.xml file of specific theme + * + * @param string $theme_folder + * @return array|bool $xmlArray OR boolean FALSE if result is no array + */ + function get_theme_xml($theme_folder) + { + if(!defined("SITEURL")) + { + define("SITEURL",""); + } + $path = $this->e107->e107_dirs['THEMES_DIRECTORY'].$theme_folder."/theme.xml"; + + if(!is_readable($path)) + { + return FALSE; + } + + // require_once($this->e107->e107_dirs['HANDLERS_DIRECTORY']."theme_handler.php"); + // $tm = new themeHandler; + $xmlArray = e107::getTheme($theme_folder, $this->debug)->get(); + + return (is_array($xmlArray)) ? $xmlArray : false; + } + + /** + * finish_form - pass data along forms + * + * @param string $force_stage [optional] + * @return none + */ + function finish_form($force_stage = false) + { + global $e_forms; + if($this->previous_steps) + { + $e_forms->add_hidden_data("previous_steps", base64_encode(serialize($this->previous_steps))); + } + $e_forms->add_hidden_data("stage", ($force_stage ? $force_stage : ($this->stage + 1))); + } + + /** + * check_writable_perms - check writable permissions + * + * @param string $list [default 'must_write'] + * @return array $bad_files + */ + function check_writable_perms($list = 'must_write') + { + $bad_files = array(); + + $system_dirs = $this->e107->e107_dirs; + $system_dirs['MEDIA_DIRECTORY'] = str_replace("[hash]/","", $system_dirs['MEDIA_DIRECTORY']); + $system_dirs['SYSTEM_DIRECTORY'] = str_replace("[hash]/","", $system_dirs['SYSTEM_DIRECTORY']); + + $data['must_write'] = 'e107_config.php|{$MEDIA_DIRECTORY}|{$SYSTEM_DIRECTORY}'; // all-sub folders are created on-the-fly + + $data['can_write'] = '{$PLUGINS_DIRECTORY}|{$THEMES_DIRECTORY}|{$WEB_DIRECTORY}cache|{$WEB_DIRECTORY}lib'; + if (!isset($data[$list])) return $bad_files; + foreach ($system_dirs as $dir_name => $value) + { + $find[] = "{\${$dir_name}}"; + $replace[] = "./$value"; + } + $data[$list] = str_replace($find, $replace, $data[$list]); + $files = explode("|", trim($data[$list])); + foreach ($files as $file) + { + if(!is_writable($file)) + { + $bad_files[] = str_replace("./", "", $file); + } + } + return $bad_files; + } + + /** + * Create Core MySQL tables + * + * @return string|FALSE error code or FALSE if no errors are detected + */ + public function create_tables() + { + // $link = mysql_connect($this->previous_steps['mysql']['server'], $this->previous_steps['mysql']['user'], $this->previous_steps['mysql']['password']); + + $link = e107::getDb()->connect($this->previous_steps['mysql']['server'], $this->previous_steps['mysql']['user'], $this->previous_steps['mysql']['password']); + + if(!$link) + { + return nl2br(LANINS_084."\n\n".LANINS_083."\n".e107::getDb()->getLastErrorText().""); + } + + $this->dbLink = $link; // Needed for mysql_close() to work round bug in PHP 5.3 + // $db_selected = mysql_select_db($this->previous_steps['mysql']['db'], $link); + $db_selected = e107::getDb()->database($this->previous_steps['mysql']['db'],$this->previous_steps['mysql']['prefix']); + if(!$db_selected) + { + return nl2br(LANINS_085." '{$this->previous_steps['mysql']['db']}'\n\n".LANINS_083."\n".e107::getDb()->getLastErrorText().""); + } + + $filename = "{$this->e107->e107_dirs['CORE_DIRECTORY']}sql/core_sql.php"; + $fd = fopen ($filename, "r"); + $sql_data = fread($fd, filesize($filename)); + $sql_data = preg_replace("#\/\*.*?\*\/#mis", '', $sql_data); // Strip comments + fclose ($fd); + + if (!$sql_data) + { + return nl2br(LANINS_060)."

    "; + } + + preg_match_all("/create(.*?)(?:myisam|innodb);/si", $sql_data, $result ); + + // Force UTF-8 again + $this->dbqry('SET NAMES `utf8`'); + + $srch = array("CREATE TABLE","("); + $repl = array("DROP TABLE IF EXISTS",""); + + foreach ($result[0] as $sql_table) + { + $sql_table = preg_replace("/create table\s/si", "CREATE TABLE {$this->previous_steps['mysql']['prefix']}", $sql_table); + + // Drop existing tables before creating. + $tmp = explode("\n",$sql_table); + $drop_table = str_replace($srch,$repl,$tmp[0]); + $this->dbqry($drop_table); + + if (!$this->dbqry($sql_table, $link)) + { + if($this->debug) + { + echo "

    filename

    "; + var_dump($filename); + + echo "

    sql_table

    "; + var_dump($sql_table); + echo "

    result[0]

    "; + var_dump($result[0]); + } + return nl2br(LANINS_061."\n\n".LANINS_083."\n".e107::getDb()->getLastErrorText().""); + } + } + + return FALSE; + + } + + function write_config($data) + { + $e107_config = 'e107_config.php'; + $fp = @fopen($e107_config, 'w'); + if (!@fwrite($fp, $data)) + { + @fclose ($fp); + return nl2br(LANINS_070); + } + @fclose ($fp); + @chmod($e107_config,0644); // correct permissions. + return false; + } + + function dbqry($qry) + { + $sql = e107::getDb(); + return $sql->db_Query($qry); + + /*if($error = $sql->getLastErrorNumber()) + { + $errorInfo = 'Query Error [#'.$error.']: '.$sql->getLastErrorText()."\nQuery: {$qry}"; + $this->debug_db_info['db_error_log'][] = $errorInfo; + return false; + } + + return true;*/ + } +} + +class e_forms +{ + var $form; + var $opened; + + function start_form($id, $action, $method = "post" ) + { + $this->form = "\n
    \n"; + $this->opened = true; + } + + function add_select_item($id, $labels, $selected) + { + $this->form .= " + \n"; + } + + + + function add_hidden_data($id, $data) + { + $this->form .= "\n"; + } + + function add_plain_html($html_data) + { + $this->form .= $html_data; + } + + function return_form() + { + if($this->opened == true) + { + $this->form .= "
    \n"; + } + $this->opened = false; + return $this->form; + } +} + +function create_tables_unattended() +{ + //If username or password not specified, exit + if(!isset($_GET['username']) || !isset($_GET['password'])) + { + return false; + } + + $mySQLserver = null; + + if(file_exists('e107_config.php')) + { + @include('e107_config.php'); + } else { + return false; + } + + //If mysql info not set, config file is not created properly + if(!isset($mySQLuser) || !isset($mySQLpassword) || !isset($mySQLdefaultdb) || !isset($mySQLprefix)) + { + return false; + } + + // If specified username and password does not match the ones in config, exit + if($_GET['username'] !== $mySQLuser || $_GET['password'] !== $mySQLpassword) + { + return false; + } + + $einstall = new e_install(); + $einstall->previous_steps['mysql']['server'] = $mySQLserver; + $einstall->previous_steps['mysql']['user'] = $mySQLuser; + $einstall->previous_steps['mysql']['password'] = $mySQLpassword; + $einstall->previous_steps['mysql']['db'] = $mySQLdefaultdb; + $einstall->previous_steps['mysql']['prefix'] = $mySQLprefix; + + $einstall->previous_steps['language'] = (isset($_GET['language']) ? $_GET['language'] : 'English'); + + $einstall->previous_steps['admin']['display'] = (isset($_GET['admin_display']) ? $_GET['admin_display'] : 'admin'); + $einstall->previous_steps['admin']['user'] = (isset($_GET['admin_user']) ? $_GET['admin_user'] : 'admin'); + $einstall->previous_steps['admin']['password'] = (isset($_GET['admin_password']) ? $_GET['admin_password'] : 'admin_password'); + $einstall->previous_steps['admin']['email'] = (isset($_GET['admin_email']) ? $_GET['admin_email'] : 'admin_email@xxx.com'); + + $einstall->previous_steps['generate_content'] = isset($_GET['gen']) ? intval($_GET['gen']) : 1; + $einstall->previous_steps['install_plugins'] = isset($_GET['plugins']) ? intval($_GET['plugins']) : 1; + $einstall->previous_steps['prefs']['sitename'] = isset($_GET['sitename']) ? urldecode($_GET['sitename']) : LANINS_113; + $einstall->previous_steps['prefs']['sitetheme'] = isset($_GET['theme']) ? urldecode($_GET['theme']) : 'bootstrap3'; + + //@include_once("./{$HANDLERS_DIRECTORY}e107_class.php"); + //$e107_paths = compact('ADMIN_DIRECTORY', 'FILES_DIRECTORY', 'IMAGES_DIRECTORY', 'THEMES_DIRECTORY', 'PLUGINS_DIRECTORY', 'HANDLERS_DIRECTORY', 'LANGUAGES_DIRECTORY', 'HELP_DIRECTORY', 'CACHE_DIRECTORY', 'DOWNLOADS_DIRECTORY', 'UPLOADS_DIRECTORY'); + //$e107 = e107::getInstance(); + //$e107->init($e107_paths, realpath(dirname(__FILE__))); + + //$einstall->e107 = &$e107; + + //FIXME - does not appear to work for import_configuration. ie. tables are blank except for user table. + + $einstall->create_tables(); + $einstall->import_configuration(); + return true; +} + +class SimpleTemplate +{ + var $Tags = array(); + var $open_tag = "{"; + var $close_tag = "}"; + + function __construct() + { + define("TEMPLATE_TYPE_FILE", 0); + define("TEMPLATE_TYPE_DATA", 1); + } + + function SetTag($TagName, $Data) + { + $this->Tags[$TagName] = array( 'Tag' => $TagName, + 'Data' => $Data + ); + } + + function RemoveTag($TagName) + { + unset($this->Tags[$TagName]); + } + + function ClearTags() + { + $this->Tags = array(); + } + + function ParseTemplate($Template, $template_type = TEMPLATE_TYPE_FILE) + { + if($template_type == TEMPLATE_TYPE_DATA) + { + $TemplateData = $Template; + } + else + { + $TemplateData = file_get_contents($Template); + } + foreach ($this->Tags as $Tag) + { + $TemplateData = str_replace($this->open_tag.$Tag['Tag'].$this->close_tag, $Tag['Data'], $TemplateData); + } + + return $TemplateData; + } +} + +function template_data() +{ + + $data = ' + + + + {installation_heading} :: {stage_pre}{stage_num} - {stage_title} + + + + + + + + + + +
    + + + +
    +
    +

    {stage_title}

    +
    +
    + {stage_content} +
    +
    + + + + +
    {debug_info}
    +
    + + + + + + + + + + + + + '; + return $data; +} + +/** + * Render a Fatal error and halt installation. + */ +function die_fatal_error($error) +{ + + define("e_IMAGE","e107_images/"); + define("e_JS","e107_web/js/"); + define("e_THEME", "e107_themes/"); + define("e_LANGUAGEDIR", "e107_languages/"); + + include(e_LANGUAGEDIR."English/English.php"); + include(e_LANGUAGEDIR."English/lan_installer.php"); + + $var = array(); + $var["installation_heading"] = LANINS_001; + $var["stage_pre"] = LANINS_002; + $var["stage_num"] = LANINS_003; + $var["stage_title"] = LAN_ERROR; + $var["percent"] = 10; + $var["bartype"] = 'danger'; + $var['stage_content'] = "
    ".$error."
    "; + $var['debug_info'] = ''; + + $template = template_data(); + + foreach($var as $k=>$val) + { + $template = str_replace("{".$k."}", $val, $template); + + } + echo $template; + exit; +} + diff --git a/login.php b/login.php index d5f6b6c2b..2d0210180 100644 --- a/login.php +++ b/login.php @@ -1,126 +1,126 @@ -getPreviousUrl(); - - if(!empty($prev)) - { - e107::redirect($prev); - exit(); - } - - e107::redirect(); - exit(); -} - -e107::coreLan('login'); - -if(!defined('e_IFRAME')) define('e_IFRAME',true); -require_once(HEADERF); -$use_imagecode = ($pref['logcode'] && extension_loaded("gd")); - -define("LOGIN_CAPTCHA", $use_imagecode); - -//if (LOGIN_CAPTCHA) -//{ - //require_once(e_HANDLER."secure_img_handler.php"); - //$sec_img = new secure_image; -//} - -if (!USER || getperms('0')) -{ - if (!defined('LOGINMESSAGE')) define('LOGINMESSAGE', ''); // LOGINMESSAGE only appears with errors - require_once(e_HANDLER.'form_handler.php'); // required for BC - $rs = new form; // required for BC - - if (empty($LOGIN_TABLE)) - { - - if(deftrue('BOOTSTRAP')) - { - $LOGIN_TEMPLATE = e107::getCoreTemplate('login'); - } - else // BC Stuff. - { - - if (file_exists(THEME.'templates/login_template.php')) //v2.x path - { - require_once(THEME.'templates/login_template.php'); - } - elseif (file_exists(THEME.'login_template.php')) - { - require_once(THEME.'login_template.php'); - } - else - { - $LOGIN_TEMPLATE = e107::getCoreTemplate('login'); - } - } - } - - - $sc = e107::getScBatch('login'); - $sc->wrapper('login/page'); - - - if(!empty($LOGIN_TEMPLATE['page'])) - { - $LOGIN_TABLE_HEADER = $LOGIN_TEMPLATE['page']['header']; - $LOGIN_TABLE = ""; - $LOGIN_TABLE_FOOTER = $LOGIN_TEMPLATE['page']['footer']; - } - - - $text = $tp->parseTemplate($LOGIN_TABLE,true, $sc); - - if(getperms('0')) - { - $find = array('[', ']'); - $replace = array("", ""); - $return_link = str_replace($find, $replace, LAN_LOGIN_33); - - echo "
    ".LAN_LOGIN_32."

    ".$return_link."
    "; - - if(empty($pref['user_reg'])) - { - $find = array('[', ']'); - $replace = array("", ""); - $pref_link = str_replace($find, $replace, LAN_LOGIN_35); - - echo "
    ".LAN_LOGIN_34."

    ".$pref_link."
    "; - } - - } - - - $login_message = SITENAME; // $login_message = LAN_LOGIN_3." | ".SITENAME; - if(strpos($LOGIN_TABLE_HEADER,'LOGIN_TABLE_LOGINMESSAGE') === false && strpos($LOGIN_TABLE,'LOGIN_TABLE_LOGINMESSAGE') === false) - { - echo LOGINMESSAGE; - } - - echo $tp->parseTemplate($LOGIN_TABLE_HEADER,true, $sc); - $ns->tablerender($login_message, $text, 'login_page'); - echo $tp->parseTemplate($LOGIN_TABLE_FOOTER, true, $sc); - -} - -require_once(FOOTERF); - -exit; - +getPreviousUrl(); + + if(!empty($prev)) + { + e107::redirect($prev); + exit(); + } + + e107::redirect(); + exit(); +} + +e107::coreLan('login'); + +if(!defined('e_IFRAME')) define('e_IFRAME',true); +require_once(HEADERF); +$use_imagecode = ($pref['logcode'] && extension_loaded("gd")); + +define("LOGIN_CAPTCHA", $use_imagecode); + +//if (LOGIN_CAPTCHA) +//{ + //require_once(e_HANDLER."secure_img_handler.php"); + //$sec_img = new secure_image; +//} + +if (!USER || getperms('0')) +{ + if (!defined('LOGINMESSAGE')) define('LOGINMESSAGE', ''); // LOGINMESSAGE only appears with errors + require_once(e_HANDLER.'form_handler.php'); // required for BC + $rs = new form; // required for BC + + if (empty($LOGIN_TABLE)) + { + + if(deftrue('BOOTSTRAP')) + { + $LOGIN_TEMPLATE = e107::getCoreTemplate('login'); + } + else // BC Stuff. + { + + if (file_exists(THEME.'templates/login_template.php')) //v2.x path + { + require_once(THEME.'templates/login_template.php'); + } + elseif (file_exists(THEME.'login_template.php')) + { + require_once(THEME.'login_template.php'); + } + else + { + $LOGIN_TEMPLATE = e107::getCoreTemplate('login'); + } + } + } + + + $sc = e107::getScBatch('login'); + $sc->wrapper('login/page'); + + + if(!empty($LOGIN_TEMPLATE['page'])) + { + $LOGIN_TABLE_HEADER = $LOGIN_TEMPLATE['page']['header']; + $LOGIN_TABLE = ""; + $LOGIN_TABLE_FOOTER = $LOGIN_TEMPLATE['page']['footer']; + } + + + $text = $tp->parseTemplate($LOGIN_TABLE,true, $sc); + + if(getperms('0')) + { + $find = array('[', ']'); + $replace = array("", ""); + $return_link = str_replace($find, $replace, LAN_LOGIN_33); + + echo "
    ".LAN_LOGIN_32."

    ".$return_link."
    "; + + if(empty($pref['user_reg'])) + { + $find = array('[', ']'); + $replace = array("", ""); + $pref_link = str_replace($find, $replace, LAN_LOGIN_35); + + echo "
    ".LAN_LOGIN_34."

    ".$pref_link."
    "; + } + + } + + + $login_message = SITENAME; // $login_message = LAN_LOGIN_3." | ".SITENAME; + if(strpos($LOGIN_TABLE_HEADER,'LOGIN_TABLE_LOGINMESSAGE') === false && strpos($LOGIN_TABLE,'LOGIN_TABLE_LOGINMESSAGE') === false) + { + echo LOGINMESSAGE; + } + + echo $tp->parseTemplate($LOGIN_TABLE_HEADER,true, $sc); + $ns->tablerender($login_message, $text, 'login_page'); + echo $tp->parseTemplate($LOGIN_TABLE_FOOTER, true, $sc); + +} + +require_once(FOOTERF); + +exit; + ?> \ No newline at end of file diff --git a/thumb.php b/thumb.php index ea0bd3eba..817a07a3f 100755 --- a/thumb.php +++ b/thumb.php @@ -1,543 +1,543 @@ -getMessage(); - -} - -function thumbErrorHandler($errno, $errstr, $errfile, $errline) -{ - - switch($errno) - { - case E_USER_ERROR: - echo "My ERROR [$errno] $errstr
    \n"; - echo " Fatal error on line $errline in file $errfile"; - echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")
    \n"; - echo "Aborting...
    \n"; - thumbExceptionHandler(new Exception); - exit(1); - break; - - default: - return; - } - -} - -set_exception_handler('thumbExceptionHandler'); // disable to troubleshoot. -set_error_handler("thumbErrorHandler"); // disable to troubleshoot. - -// error_reporting(0); // suppress all errors or image will be corrupted. - - - -ini_set('gd.jpeg_ignore_warning', 1); -//require_once './e107_handlers/benchmark.php'; -//$bench = new e_benchmark(); -//$bench->start(); - -$thumbpage = new e_thumbpage(); - -if(!$thumbpage->checkSrc()) -{ - die(' Access denied!'); -} -$thumbpage->sendImage(); - -// Check your e_LOG folder -//$bench->end()->logResult('thumb.php', $_GET['src'].' - no cache'); -exit; - -class e_thumbpage -{ - private $_debug = false; - - private $_cache = true; - - /** - * Page request - * @var array - */ - protected $_request = array(); - - /** - * @var string image source path (e107 path shortcode) - */ - protected $_src = null; - - /** - * @var string source path modified/sanitized - */ - protected $_src_path = null; - - - /** Stores watermark prefs - */ - protected $_watermark = array(); - - private $_placeholder = false; - - protected $_thumbQuality = null; - - /** - * Constructor - init paths - * @todo FIX e107 (new folder structure), simplify all this, e.g. e107::getInstance()->initMinimal($path_to_e107_config); - * - * @return void - */ - public function __construct() - { - // initial path - $self = realpath(dirname(__FILE__)); - - $e_ROOT = $self."/"; - - if ((substr($e_ROOT,-1) !== '/') && (substr($e_ROOT,-1) !== '\\') ) - { - $e_ROOT .= DIRECTORY_SEPARATOR; // Should function correctly on both windows and Linux now. - } - - define('e_ROOT', $e_ROOT); - - $mySQLdefaultdb = ''; - $HANDLERS_DIRECTORY = ''; - $mySQLprefix = ''; - - // Config - - include($self.DIRECTORY_SEPARATOR.'e107_config.php'); - - // support early include feature - if(isset($CLASS2_INCLUDE) && !empty($CLASS2_INCLUDE)) - { - require_once(realpath(dirname(__FILE__).'/'.$CLASS2_INCLUDE)); - } - - - ob_end_clean(); // Precaution - clearout utf-8 BOM or any other garbage in e107_config.php - - if(empty($HANDLERS_DIRECTORY)) - { - $HANDLERS_DIRECTORY = 'e107_handlers/'; // quick fix for CLI Unit test. - } - - $tmp = $self.DIRECTORY_SEPARATOR.$HANDLERS_DIRECTORY; - - //Core functions - now API independent - @require($tmp.DIRECTORY_SEPARATOR.'core_functions.php'); - //e107 class - @require($tmp.DIRECTORY_SEPARATOR.'e107_class.php'); - - $e107_paths = compact( - 'ADMIN_DIRECTORY', - 'FILES_DIRECTORY', - 'IMAGES_DIRECTORY', - 'THEMES_DIRECTORY', - 'PLUGINS_DIRECTORY', - 'HANDLERS_DIRECTORY', - 'LANGUAGES_DIRECTORY', - 'HELP_DIRECTORY', - 'DOWNLOADS_DIRECTORY', - 'UPLOADS_DIRECTORY', - 'MEDIA_DIRECTORY', - 'CACHE_DIRECTORY', - 'LOGS_DIRECTORY', - 'WEB_DIRECTORY', - 'SYSTEM_DIRECTORY', - 'CORE_DIRECTORY' - ); - // $sql_info = array(); //compact('mySQLserver', 'mySQLuser', 'mySQLpassword', 'mySQLdefaultdb', 'mySQLprefix', 'mySQLcharset'); - //e107::getInstance()->initCore($e107_paths, $self, $sql_info, varset($e107_CONFIG, array())); - $e107 = e107::getInstance(); - - $e107->site_path = substr(md5($mySQLdefaultdb.".".$mySQLprefix),0,10); - - $e107->prepare_request(); - $e107->setDirs($e107_paths, varset($E107_CONFIG, array())); - $e107->set_constants(); - $e107->set_paths(); - $e107->file_path = $e107->fix_windows_paths($self)."/"; - $e107->set_base_path(); - $e107->set_request(false); - // $e107->set_urls(false); //todo check if this is still required after the 'prepare' issue is fixed. - unset($tmp, $self); - $e107->set_urls(false); - // basic Admin area detection - required for proper path parsing - define('ADMIN', strpos(e_SELF, ($e107->getFolder('admin')) !== false || strpos(e_PAGE, 'admin') !== false)); - - // Next function call maintains behavior identical to before; might not be needed - // See https://github.com/e107inc/e107/issues/3033 - $e107->set_urls_deferred(); - - $pref = $e107->getPref(); //TODO optimize/benchmark - - $this->_watermark = array( - 'activate' => vartrue($pref['watermark_activate'], false), - 'text' => vartrue($pref['watermark_text']), - 'size' => vartrue($pref['watermark_size'], 20), - 'pos' => vartrue($pref['watermark_pos'],"BR"), - 'color' => vartrue($pref['watermark_color'],'fff'), - 'font' => vartrue($pref['watermark_font']), - 'margin' => vartrue($pref['watermark_margin'],30), - 'shadowcolor' => vartrue($pref['watermark_shadowcolor'], '000000'), - 'opacity' => vartrue($pref['watermark_opacity'], 20) - ); - - $this->_thumbQuality = vartrue($pref['thumbnail_quality'],65); - - - // parse request - $this->parseRequest(); - } - - function parseRequest() - { - //echo 'e_query='.str_replace('&', '&', e_QUERY); - $e_QUERY = e_QUERY; - - if(isset($_GET['id'])) // very-basic url-tampering prevention and path cloaking - { - $e_QUERY = base64_decode($_GET['id']); - } - - parse_str(str_replace('&', '&', $e_QUERY), $this->_request); - - // parse_str($_SERVER['QUERY_STRING'], $this->_request); - return $this; - } - - function checkSrc() - { - if(!vartrue($this->_request['src'])) // display placeholder when src is missing. - { - $this->_placeholder = true; - return true; - } - - $tp = e107::getParser(); - - // convert raw to SC path - $this->_request['src'] = str_replace($tp->getUrlConstants('raw'), $tp->getUrlConstants('sc'), $this->_request['src']); - - // convert absolute and full url to SC URL - $this->_src = $tp->createConstants($this->_request['src'], 'mix'); - - if(preg_match('#^(https?|ftps?|file)://#i', $this->_request['src'])) - { - return false; - } - - if(!is_writeable(e_CACHE_IMAGE)) - { - echo 'Cache folder not writeable! '; - return false; - } - - // convert to relative server path - $path = $tp->replaceConstants(str_replace('..', '', $this->_src)); //should be safe enough - - if(is_file($path) && is_readable($path)) - { - $this->_src_path = $path; - return true; - } - - if($this->_debug === true) - { - echo "File Not Found: ".$path; - } - - $this->_placeholder = true; - return true; - - } - - - function sendImage() - { - //global $bench; - if($this->_debug === true) - { - var_dump($this->_request); - // return false; - } - - - if($this->_placeholder == true) - { - $width = ($this->_request['aw']) ? $this->_request['aw'] : $this->_request['w']; - $height = ($this->_request['ah']) ? $this->_request['ah'] : $this->_request['h']; - - $parm = array('size' => $width."x".$height); - - $this->placeholder($parm); - return false; - } - - - - if(!$this->_src_path) - { - return $this; - } - - $thumbnfo = pathinfo($this->_src_path); - $options = $this->getRequestOptions(); - - if($this->_debug === true) - { - var_dump($options); - // return false; - } - - // $cache_str = md5(serialize($options). $this->_src_path. $this->_thumbQuality); - // $fname = strtolower('Thumb_'.$thumbnfo['filename'].'_'.$cache_str.'.'.$thumbnfo['extension']).'.cache.bin'; - - $fname = e107::getParser()->thumbCacheFile($this->_src_path, $options); - - $cache_filename = e_CACHE_IMAGE . $fname; - if(($this->_cache === true) && is_file($cache_filename) && is_readable($cache_filename) && ($this->_debug !== true)) - { - $thumbnfo['lmodified'] = filemtime($cache_filename); - $thumbnfo['md5s'] = md5_file($cache_filename); - $thumbnfo['fsize'] = filesize($cache_filename); - - // Send required headers - if($this->_debug !== true) - { - $this->sendHeaders($thumbnfo); - } - - //$bench->end()->logResult('thumb.php', $_GET['src'].' - 304 not modified'); - // exit; - // check browser cache - if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] && ($thumbnfo['lmodified'] <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) && (isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) == $thumbnfo['md5s'])) - { - header('HTTP/1.1 304 Not Modified'); - //$bench->end()->logResult('thumb.php', $_GET['src'].' - 304 not modified'); - exit; - } - - // Send required headers - //$this->sendHeaders($thumbnfo); - - eShims::readfile($cache_filename); - //$bench->end()->logResult('thumb.php', $_GET['src'].' - retrieve cache'); - - exit; - } - - // TODO - wrap it around generic e107 thumb handler - if($this->_debug === true) - { - $start = microtime(true); - } - @require(e_HANDLER.'phpthumb/ThumbLib.inc.php'); - try - { - $thumb = PhpThumbFactory::create($this->_src_path); - $sizeUp = ($this->_request['w'] > 110 || $this->_request['aw'] > 110) ? true : false; // don't resizeUp the icon images. - $thumb->setOptions(array( - 'correctPermissions' => true, - 'resizeUp' => $sizeUp, - 'jpegQuality' => $this->_thumbQuality, - 'interlace' => true // improves performance - )); - - } - catch (Exception $e) - { - echo $e->getMessage(); - return $this; - } - - // Image Cropping by Quadrant. - if(!empty($options['c'])) // $quadrant T(op), B(ottom), C(enter), L(eft), R(right) - { - if(!empty($this->_request['ah'])) - { - $this->_request['h'] = $this->_request['ah']; - } - - if(!empty($this->_request['aw'])) - { - $this->_request['w'] = $this->_request['aw']; - } - - - - $thumb->adaptiveResizeQuadrant((integer) vartrue($this->_request['w'], 0), (integer) vartrue($this->_request['h'], 0), $options['c']); - } - if(isset($this->_request['w']) || isset($this->_request['h'])) - { - $thumb->resize((integer) vartrue($this->_request['w'], 0), (integer) vartrue($this->_request['h'], 0)); - } - elseif(!empty($this->_request['ah'])) - { - //Typically gives a better result with images of people than adaptiveResize(). - //TODO TBD Add Pref for Top, Bottom, Left, Right, Center? - $thumb->adaptiveResizeQuadrant((integer) vartrue($this->_request['aw'], 0), (integer) vartrue($this->_request['ah'], 0), 'T'); - } - else - { - $thumb->adaptiveResize((integer) vartrue($this->_request['aw'], 0), (integer) vartrue($this->_request['ah'], 0)); - } - - - if($this->_debug === true) - { - echo "time: ".round((microtime(true) - $start),4); - - var_dump($thumb); - return false; - } - - // Watermark Option - See admin->MediaManager->prefs for details. - - if(($this->_watermark['activate'] < $options['w'] - || $this->_watermark['activate'] < $options['aw'] - || $this->_watermark['activate'] < $options['h'] - || $this->_watermark['activate'] < $options['ah'] - ) && $this->_watermark['activate'] > 0 && $this->_watermark['font'] !='') - { - $tp = e107::getParser(); - $this->_watermark['font'] = $tp->createConstants($this->_watermark['font'], 'mix'); - $this->_watermark['font'] = realpath($tp->replaceConstants($this->_watermark['font'],'rel')); - - $thumb->WatermarkText($this->_watermark); - } - // echo "hello"; - - - - //exit; - - // set cache - $thumb->save($cache_filename); - - - - // show thumb - $thumb->show(); - } - - function getRequestOptions() - { - $ret = array(); - $ret['w'] = isset($this->_request['w']) ? intval($this->_request['w']) : false; - $ret['h'] = isset($this->_request['h']) ? intval($this->_request['h']) : $ret['w']; - $ret['aw'] = isset($this->_request['aw']) ? intval($this->_request['aw']) : false; - $ret['ah'] = isset($this->_request['ah']) ? intval($this->_request['ah']) : $ret['aw']; - $ret['c'] = isset($this->_request['c']) ? strtoupper(substr(filter_var($this->_request['c'],FILTER_SANITIZE_STRING),0,1)) : false; - // $ret['wm'] = isset($this->_request['wm']) ? intval($this->_request['wm']) : $ret['wm']; - - if($ret['c'] == 'A') // auto - { - $ret['c'] = 'T'; // default is 'Top'; - } - - return $ret; - } - - public function sendHeaders($thumbnfo) - { - if(headers_sent($filename, $linenum)) - { - echo 'Headers already sent in '.$filename.' on line '.$linenum; - exit; - } - - if (function_exists('date_default_timezone_set')) - { - date_default_timezone_set('UTC'); - } - //header('Pragma:'); - header('Cache-Control: must-revalidate'); - // header('Cache-Control: public, max-age=3600'); - header('Last-Modified: '.gmdate('D, d M Y H:i:s', $thumbnfo['lmodified']).' GMT'); - header('Content-Length: '.$thumbnfo['fsize']); - header('Content-Disposition: filename='.$thumbnfo['basename']); // important for right-click save-as. - - $ctype = self::ctype($thumbnfo['extension']); - if(null !== $ctype) - { - header('Content-Type: '.$ctype); - } - - // Expire header - 1 year - $time = time() + 365 * 86400; - header('Expires: '.gmdate("D, d M Y H:i:s", $time).' GMT'); - header("Etag: ".$thumbnfo['md5s']); - - } - - - - public static function ctype($ftype) - { - static $known_types = array( - 'gif' => 'image/gif', - 'jpg' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'png' => 'image/png', - //'bmp' => 'image/bmp', - ); - - $ftype = strtolower($ftype); - if(isset($known_types[$ftype])) - { - return $known_types[$ftype]; - } - return null; - } - - - // Display a placeholder image. - function placeholder($parm) - { - if($this->_debug === true) - { - echo "Placeholder activated"; - return null; - } - - $getsize = isset($parm['size']) ? $parm['size'] : '100x100'; - - header('location: https://placehold.it/'.$getsize); - header('Content-Length: 0'); - exit(); - } - - -} - -?> +getMessage(); + +} + +function thumbErrorHandler($errno, $errstr, $errfile, $errline) +{ + + switch($errno) + { + case E_USER_ERROR: + echo "My ERROR [$errno] $errstr
    \n"; + echo " Fatal error on line $errline in file $errfile"; + echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")
    \n"; + echo "Aborting...
    \n"; + thumbExceptionHandler(new Exception); + exit(1); + break; + + default: + return; + } + +} + +set_exception_handler('thumbExceptionHandler'); // disable to troubleshoot. +set_error_handler("thumbErrorHandler"); // disable to troubleshoot. + +// error_reporting(0); // suppress all errors or image will be corrupted. + + + +ini_set('gd.jpeg_ignore_warning', 1); +//require_once './e107_handlers/benchmark.php'; +//$bench = new e_benchmark(); +//$bench->start(); + +$thumbpage = new e_thumbpage(); + +if(!$thumbpage->checkSrc()) +{ + die(' Access denied!'); +} +$thumbpage->sendImage(); + +// Check your e_LOG folder +//$bench->end()->logResult('thumb.php', $_GET['src'].' - no cache'); +exit; + +class e_thumbpage +{ + private $_debug = false; + + private $_cache = true; + + /** + * Page request + * @var array + */ + protected $_request = array(); + + /** + * @var string image source path (e107 path shortcode) + */ + protected $_src = null; + + /** + * @var string source path modified/sanitized + */ + protected $_src_path = null; + + + /** Stores watermark prefs + */ + protected $_watermark = array(); + + private $_placeholder = false; + + protected $_thumbQuality = null; + + /** + * Constructor - init paths + * @todo FIX e107 (new folder structure), simplify all this, e.g. e107::getInstance()->initMinimal($path_to_e107_config); + * + * @return void + */ + public function __construct() + { + // initial path + $self = realpath(dirname(__FILE__)); + + $e_ROOT = $self."/"; + + if ((substr($e_ROOT,-1) !== '/') && (substr($e_ROOT,-1) !== '\\') ) + { + $e_ROOT .= DIRECTORY_SEPARATOR; // Should function correctly on both windows and Linux now. + } + + define('e_ROOT', $e_ROOT); + + $mySQLdefaultdb = ''; + $HANDLERS_DIRECTORY = ''; + $mySQLprefix = ''; + + // Config + + include($self.DIRECTORY_SEPARATOR.'e107_config.php'); + + // support early include feature + if(isset($CLASS2_INCLUDE) && !empty($CLASS2_INCLUDE)) + { + require_once(realpath(dirname(__FILE__).'/'.$CLASS2_INCLUDE)); + } + + + ob_end_clean(); // Precaution - clearout utf-8 BOM or any other garbage in e107_config.php + + if(empty($HANDLERS_DIRECTORY)) + { + $HANDLERS_DIRECTORY = 'e107_handlers/'; // quick fix for CLI Unit test. + } + + $tmp = $self.DIRECTORY_SEPARATOR.$HANDLERS_DIRECTORY; + + //Core functions - now API independent + @require($tmp.DIRECTORY_SEPARATOR.'core_functions.php'); + //e107 class + @require($tmp.DIRECTORY_SEPARATOR.'e107_class.php'); + + $e107_paths = compact( + 'ADMIN_DIRECTORY', + 'FILES_DIRECTORY', + 'IMAGES_DIRECTORY', + 'THEMES_DIRECTORY', + 'PLUGINS_DIRECTORY', + 'HANDLERS_DIRECTORY', + 'LANGUAGES_DIRECTORY', + 'HELP_DIRECTORY', + 'DOWNLOADS_DIRECTORY', + 'UPLOADS_DIRECTORY', + 'MEDIA_DIRECTORY', + 'CACHE_DIRECTORY', + 'LOGS_DIRECTORY', + 'WEB_DIRECTORY', + 'SYSTEM_DIRECTORY', + 'CORE_DIRECTORY' + ); + // $sql_info = array(); //compact('mySQLserver', 'mySQLuser', 'mySQLpassword', 'mySQLdefaultdb', 'mySQLprefix', 'mySQLcharset'); + //e107::getInstance()->initCore($e107_paths, $self, $sql_info, varset($e107_CONFIG, array())); + $e107 = e107::getInstance(); + + $e107->site_path = substr(md5($mySQLdefaultdb.".".$mySQLprefix),0,10); + + $e107->prepare_request(); + $e107->setDirs($e107_paths, varset($E107_CONFIG, array())); + $e107->set_constants(); + $e107->set_paths(); + $e107->file_path = $e107->fix_windows_paths($self)."/"; + $e107->set_base_path(); + $e107->set_request(false); + // $e107->set_urls(false); //todo check if this is still required after the 'prepare' issue is fixed. + unset($tmp, $self); + $e107->set_urls(false); + // basic Admin area detection - required for proper path parsing + define('ADMIN', strpos(e_SELF, ($e107->getFolder('admin')) !== false || strpos(e_PAGE, 'admin') !== false)); + + // Next function call maintains behavior identical to before; might not be needed + // See https://github.com/e107inc/e107/issues/3033 + $e107->set_urls_deferred(); + + $pref = $e107->getPref(); //TODO optimize/benchmark + + $this->_watermark = array( + 'activate' => vartrue($pref['watermark_activate'], false), + 'text' => vartrue($pref['watermark_text']), + 'size' => vartrue($pref['watermark_size'], 20), + 'pos' => vartrue($pref['watermark_pos'],"BR"), + 'color' => vartrue($pref['watermark_color'],'fff'), + 'font' => vartrue($pref['watermark_font']), + 'margin' => vartrue($pref['watermark_margin'],30), + 'shadowcolor' => vartrue($pref['watermark_shadowcolor'], '000000'), + 'opacity' => vartrue($pref['watermark_opacity'], 20) + ); + + $this->_thumbQuality = vartrue($pref['thumbnail_quality'],65); + + + // parse request + $this->parseRequest(); + } + + function parseRequest() + { + //echo 'e_query='.str_replace('&', '&', e_QUERY); + $e_QUERY = e_QUERY; + + if(isset($_GET['id'])) // very-basic url-tampering prevention and path cloaking + { + $e_QUERY = base64_decode($_GET['id']); + } + + parse_str(str_replace('&', '&', $e_QUERY), $this->_request); + + // parse_str($_SERVER['QUERY_STRING'], $this->_request); + return $this; + } + + function checkSrc() + { + if(!vartrue($this->_request['src'])) // display placeholder when src is missing. + { + $this->_placeholder = true; + return true; + } + + $tp = e107::getParser(); + + // convert raw to SC path + $this->_request['src'] = str_replace($tp->getUrlConstants('raw'), $tp->getUrlConstants('sc'), $this->_request['src']); + + // convert absolute and full url to SC URL + $this->_src = $tp->createConstants($this->_request['src'], 'mix'); + + if(preg_match('#^(https?|ftps?|file)://#i', $this->_request['src'])) + { + return false; + } + + if(!is_writeable(e_CACHE_IMAGE)) + { + echo 'Cache folder not writeable! '; + return false; + } + + // convert to relative server path + $path = $tp->replaceConstants(str_replace('..', '', $this->_src)); //should be safe enough + + if(is_file($path) && is_readable($path)) + { + $this->_src_path = $path; + return true; + } + + if($this->_debug === true) + { + echo "File Not Found: ".$path; + } + + $this->_placeholder = true; + return true; + + } + + + function sendImage() + { + //global $bench; + if($this->_debug === true) + { + var_dump($this->_request); + // return false; + } + + + if($this->_placeholder == true) + { + $width = ($this->_request['aw']) ? $this->_request['aw'] : $this->_request['w']; + $height = ($this->_request['ah']) ? $this->_request['ah'] : $this->_request['h']; + + $parm = array('size' => $width."x".$height); + + $this->placeholder($parm); + return false; + } + + + + if(!$this->_src_path) + { + return $this; + } + + $thumbnfo = pathinfo($this->_src_path); + $options = $this->getRequestOptions(); + + if($this->_debug === true) + { + var_dump($options); + // return false; + } + + // $cache_str = md5(serialize($options). $this->_src_path. $this->_thumbQuality); + // $fname = strtolower('Thumb_'.$thumbnfo['filename'].'_'.$cache_str.'.'.$thumbnfo['extension']).'.cache.bin'; + + $fname = e107::getParser()->thumbCacheFile($this->_src_path, $options); + + $cache_filename = e_CACHE_IMAGE . $fname; + if(($this->_cache === true) && is_file($cache_filename) && is_readable($cache_filename) && ($this->_debug !== true)) + { + $thumbnfo['lmodified'] = filemtime($cache_filename); + $thumbnfo['md5s'] = md5_file($cache_filename); + $thumbnfo['fsize'] = filesize($cache_filename); + + // Send required headers + if($this->_debug !== true) + { + $this->sendHeaders($thumbnfo); + } + + //$bench->end()->logResult('thumb.php', $_GET['src'].' - 304 not modified'); + // exit; + // check browser cache + if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] && ($thumbnfo['lmodified'] <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) && (isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) == $thumbnfo['md5s'])) + { + header('HTTP/1.1 304 Not Modified'); + //$bench->end()->logResult('thumb.php', $_GET['src'].' - 304 not modified'); + exit; + } + + // Send required headers + //$this->sendHeaders($thumbnfo); + + eShims::readfile($cache_filename); + //$bench->end()->logResult('thumb.php', $_GET['src'].' - retrieve cache'); + + exit; + } + + // TODO - wrap it around generic e107 thumb handler + if($this->_debug === true) + { + $start = microtime(true); + } + @require(e_HANDLER.'phpthumb/ThumbLib.inc.php'); + try + { + $thumb = PhpThumbFactory::create($this->_src_path); + $sizeUp = ($this->_request['w'] > 110 || $this->_request['aw'] > 110) ? true : false; // don't resizeUp the icon images. + $thumb->setOptions(array( + 'correctPermissions' => true, + 'resizeUp' => $sizeUp, + 'jpegQuality' => $this->_thumbQuality, + 'interlace' => true // improves performance + )); + + } + catch (Exception $e) + { + echo $e->getMessage(); + return $this; + } + + // Image Cropping by Quadrant. + if(!empty($options['c'])) // $quadrant T(op), B(ottom), C(enter), L(eft), R(right) + { + if(!empty($this->_request['ah'])) + { + $this->_request['h'] = $this->_request['ah']; + } + + if(!empty($this->_request['aw'])) + { + $this->_request['w'] = $this->_request['aw']; + } + + + + $thumb->adaptiveResizeQuadrant((integer) vartrue($this->_request['w'], 0), (integer) vartrue($this->_request['h'], 0), $options['c']); + } + if(isset($this->_request['w']) || isset($this->_request['h'])) + { + $thumb->resize((integer) vartrue($this->_request['w'], 0), (integer) vartrue($this->_request['h'], 0)); + } + elseif(!empty($this->_request['ah'])) + { + //Typically gives a better result with images of people than adaptiveResize(). + //TODO TBD Add Pref for Top, Bottom, Left, Right, Center? + $thumb->adaptiveResizeQuadrant((integer) vartrue($this->_request['aw'], 0), (integer) vartrue($this->_request['ah'], 0), 'T'); + } + else + { + $thumb->adaptiveResize((integer) vartrue($this->_request['aw'], 0), (integer) vartrue($this->_request['ah'], 0)); + } + + + if($this->_debug === true) + { + echo "time: ".round((microtime(true) - $start),4); + + var_dump($thumb); + return false; + } + + // Watermark Option - See admin->MediaManager->prefs for details. + + if(($this->_watermark['activate'] < $options['w'] + || $this->_watermark['activate'] < $options['aw'] + || $this->_watermark['activate'] < $options['h'] + || $this->_watermark['activate'] < $options['ah'] + ) && $this->_watermark['activate'] > 0 && $this->_watermark['font'] !='') + { + $tp = e107::getParser(); + $this->_watermark['font'] = $tp->createConstants($this->_watermark['font'], 'mix'); + $this->_watermark['font'] = realpath($tp->replaceConstants($this->_watermark['font'],'rel')); + + $thumb->WatermarkText($this->_watermark); + } + // echo "hello"; + + + + //exit; + + // set cache + $thumb->save($cache_filename); + + + + // show thumb + $thumb->show(); + } + + function getRequestOptions() + { + $ret = array(); + $ret['w'] = isset($this->_request['w']) ? intval($this->_request['w']) : false; + $ret['h'] = isset($this->_request['h']) ? intval($this->_request['h']) : $ret['w']; + $ret['aw'] = isset($this->_request['aw']) ? intval($this->_request['aw']) : false; + $ret['ah'] = isset($this->_request['ah']) ? intval($this->_request['ah']) : $ret['aw']; + $ret['c'] = isset($this->_request['c']) ? strtoupper(substr(filter_var($this->_request['c'],FILTER_SANITIZE_STRING),0,1)) : false; + // $ret['wm'] = isset($this->_request['wm']) ? intval($this->_request['wm']) : $ret['wm']; + + if($ret['c'] == 'A') // auto + { + $ret['c'] = 'T'; // default is 'Top'; + } + + return $ret; + } + + public function sendHeaders($thumbnfo) + { + if(headers_sent($filename, $linenum)) + { + echo 'Headers already sent in '.$filename.' on line '.$linenum; + exit; + } + + if (function_exists('date_default_timezone_set')) + { + date_default_timezone_set('UTC'); + } + //header('Pragma:'); + header('Cache-Control: must-revalidate'); + // header('Cache-Control: public, max-age=3600'); + header('Last-Modified: '.gmdate('D, d M Y H:i:s', $thumbnfo['lmodified']).' GMT'); + header('Content-Length: '.$thumbnfo['fsize']); + header('Content-Disposition: filename='.$thumbnfo['basename']); // important for right-click save-as. + + $ctype = self::ctype($thumbnfo['extension']); + if(null !== $ctype) + { + header('Content-Type: '.$ctype); + } + + // Expire header - 1 year + $time = time() + 365 * 86400; + header('Expires: '.gmdate("D, d M Y H:i:s", $time).' GMT'); + header("Etag: ".$thumbnfo['md5s']); + + } + + + + public static function ctype($ftype) + { + static $known_types = array( + 'gif' => 'image/gif', + 'jpg' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'png' => 'image/png', + //'bmp' => 'image/bmp', + ); + + $ftype = strtolower($ftype); + if(isset($known_types[$ftype])) + { + return $known_types[$ftype]; + } + return null; + } + + + // Display a placeholder image. + function placeholder($parm) + { + if($this->_debug === true) + { + echo "Placeholder activated"; + return null; + } + + $getsize = isset($parm['size']) ? $parm['size'] : '100x100'; + + header('location: https://placehold.it/'.$getsize); + header('Content-Length: 0'); + exit(); + } + + +} + +?> diff --git a/top.php b/top.php index 8393afdd5..66b6f26a7 100644 --- a/top.php +++ b/top.php @@ -1,310 +1,310 @@ -getForumPermList('view')); - - $qry = " - SELECT - t.*, u.user_name, ul.user_name AS user_last, f.forum_name - FROM `#forum_thread` as t - LEFT JOIN `#forum` AS f ON f.forum_id = t.thread_forum_id - LEFT JOIN `#user` AS u ON u.user_id = t.thread_user - LEFT JOIN `#user` AS ul ON ul.user_id = t.thread_lastuser - WHERE t.thread_forum_id IN ({$forumList}) - ORDER BY t.thread_views DESC - LIMIT - {$from}, {$view} - "; - - if ($sql->gen($qry)) - { - $text = "
    \n\n"; - $gen = e107::getDate(); - - $text .= " - - - - - - - \n"; - - while ($row = $sql->fetch()) - { - if ($row['user_name']) - { - $POSTER = "{$row['user_name']}"; - } - else - { - $POSTER = $row['thread_user_anon']; - } - - $LINKTOTHREAD = e107::getUrl()->create('forum/thread/view', array('id' =>$row['thread_id'])); //$e107->url->getUrl('forum', 'thread', "func=view&id={$row['thread_id']}"); - $LINKTOFORUM = e107::getUrl()->create('forum/forum/view', array('id' => $row['thread_forum_id'])); //$e107->url->getUrl('forum', 'forum', "func=view&id={$row['thread_forum_id']}"); - - $lastpost_datestamp = $gen->convert_date($row['thread_lastpost'], 'forum'); - if ($row['user_last']) - { - $LASTPOST = "{$row['user_last']}
    ".$lastpost_datestamp; - } - else - { - $LASTPOST = $row['thread_lastuser_anon'].'
    '.$lastpost_datestamp; - } - - $text .= " - - - - - - - \n"; - } - - $text .= "
     ".LAN_1."".LAN_2."".LAN_3."".LAN_4."".LAN_5."
    {$row['thread_name']} ({$row['forum_name']}){$POSTER}{$row['thread_views']}{$row['thread_total_replies']}{$LASTPOST}
    \n
    "; - - $ftotal = $sql->db_Count('forum_thread', '(*)', 'WHERE `thread_parent` = 0'); - $parms = "{$ftotal},{$view},{$from},".e_SELF.'?[FROM].active.forum.'.$view; - $text .= "
    ".$tp->parseTemplate("{NEXTPREV={$parms}}").'
    '; - $ns->tablerender(LAN_7, $text, 'nfp'); - /* - require_once (e_HANDLER.'np_class.php'); - $ftotal = $sql->db_Count('forum_thread', '(*)', 'WHERE 1'); - $ix = new nextprev('top.php', $from, $view, $ftotal, '', 'active.forum.'.$view); - */ - } -} -if ($action == 'top') -{ - //require_once (e_HANDLER.'level_handler.php'); - $rank = e107::getRank(); - - define('IMAGE_rank_main_admin_image', ($pref['rank_main_admin_image'] && file_exists(THEME."forum/".$pref['rank_main_admin_image']) ? "" : "")); - define('IMAGE_rank_admin_image', ($pref['rank_admin_image'] && file_exists(THEME."forum/".$pref['rank_admin_image']) ? "" : "")); - define('IMAGE_rank_moderator_image', ($pref['rank_moderator_image'] && file_exists(THEME."forum/".$pref['rank_moderator_image']) ? "" : "")); - - if ($subaction == 'forum' || $subaction == 'all') - { - require_once (e_PLUGIN.'forum/forum_class.php'); - $forum = new e107forum(); - - $qry = " - SELECT ue.*, u.* FROM `#user_extended` AS ue - LEFT JOIN `#user` AS u ON u.user_id = ue.user_extended_id - WHERE ue.user_plugin_forum_posts > 0 - ORDER BY ue.user_plugin_forum_posts DESC LIMIT {$from}, {$view} - "; - // $top_forum_posters = $sql->db_Select("user", "*", "`user_forums` > 0 ORDER BY user_forums DESC LIMIT ".$from.", ".$view.""); - $text = " -
    - - - - - - - \n"; - $counter = 1 + $from; - $sql2 = e107::getDb('sql2'); - if ($sql2->gen($qry)) - { - while ($row = $sql2->fetch()) - { - //$ldata = get_level($row['user_id'], $row['user_plugin_forum_posts'], $row['user_comments'], $row['user_chats'], $row['user_visits'], $row['user_join'], $row['user_admin'], $row['user_perms'], $pref); - $ldata = $rank->getRanks($row, (USER && $forum->isModerator(USERID))); - - if(vartrue($ldata['special'])) - { - $r = $ldata['special']; - } - else - { - $r = $ldata['pic'] ? $ldata['pic'] : defset($ldata['name'], $ldata['name']); - } - if(!$r) $r = 'n/a'; - $text .= " - - - - - "; - $counter++; - } - } - $text .= "
     ".TOP_LAN_1."".TOP_LAN_2."".TOP_LAN_6."
    {$counter}{$row['user_name']}{$row['user_plugin_forum_posts']}{$r}
    \n
    "; - if ($subaction == 'forum') - { - //$ftotal = $sql->db_Count('user', '(*)', 'WHERE `user_forums` > 0'); - $ftotal = $sql->count('user_extended', '(*)', 'WHERE `user_plugin_forum_posts` > 0'); - $parms = "{$ftotal},{$view},{$from},".e_SELF.'?[FROM].top.forum.'.$view; - $text .= "
    ".$tp->parseTemplate("{NEXTPREV={$parms}}").'
    '; - } - $ns->tablerender(TOP_LAN_0, $text); - /* - if ($subaction == 'forum') - { - require_once (e_HANDLER.'np_class.php'); - $ftotal = $sql->db_Count('user_extended', '(*)', 'WHERE `user_plugin_forum_posts` > 0'); - $ix = new nextprev('top.php', $from, $view, $ftotal, 'Forum Posts', 'top.forum.'.$view); - }*/ - } - - - if ($subaction == 'comment' || $subaction == 'all') - { - $top_forum_posters = $sql->select("user", "*", "`user_comments` > 0 ORDER BY user_comments DESC LIMIT 0, 10"); - $text = " -
    - - - - - - - \n"; - $counter = 1; - if($top_forum_posters) - { - while ($row = $sql->fetch()) - { - // TODO - Custom ranking (comments), LANs - $ldata = $rank->getRanks($row); - if(vartrue($ldata['special'])) - { - $r = $ldata['special']; - } - else - { - $r = $ldata['pic'] ? $ldata['pic'] : defset($ldata['name'], $ldata['name']); - } - if(!$r) $r = 'n/a'; - $text .= " - - - - - "; - $counter++; - } - } - else - { - $text .= " - - - "; - } - $text .= "
     ".TOP_LAN_1."".LAN_COMMENTS."".TOP_LAN_6."
    {$counter}{$row['user_name']}{$row['user_comments']}{$r}
    No results
    \n
    "; - $ns->tablerender(TOP_LAN_3, $text); - } - - if ($subaction == 'chat' || $subaction == 'all') - { - $top_forum_posters = $sql->select("user", "*", "`user_chats` > 0 ORDER BY user_chats DESC LIMIT 0, 10"); - $text = " -
    - - - - - - - \n"; - $counter = 1; - if($top_forum_posters) - { - while ($row = $sql->fetch()) - { - // TODO - Custom ranking (chat), LANs - $ldata = $rank->getRanks($row); - if(vartrue($ldata['special'])) - { - $r = $ldata['special']; - } - else - { - $r = $ldata['pic'] ? $ldata['pic'] : defset($ldata['name'], $ldata['name']); - } - if(!$r) $r = 'n/a'; - $text .= " - - - - - "; - $counter++; - } - - } - else - { - $text .= " - - - "; - } - $text .= "
     ".TOP_LAN_1."".TOP_LAN_2."".TOP_LAN_6."
    {$counter}{$row['user_name']}{$row['user_chats']}{$r}
    No results
    \n
    "; - $ns->tablerender(TOP_LAN_5, $text); - } -} -require_once(FOOTERF); +getForumPermList('view')); + + $qry = " + SELECT + t.*, u.user_name, ul.user_name AS user_last, f.forum_name + FROM `#forum_thread` as t + LEFT JOIN `#forum` AS f ON f.forum_id = t.thread_forum_id + LEFT JOIN `#user` AS u ON u.user_id = t.thread_user + LEFT JOIN `#user` AS ul ON ul.user_id = t.thread_lastuser + WHERE t.thread_forum_id IN ({$forumList}) + ORDER BY t.thread_views DESC + LIMIT + {$from}, {$view} + "; + + if ($sql->gen($qry)) + { + $text = "
    \n\n"; + $gen = e107::getDate(); + + $text .= " + + + + + + + \n"; + + while ($row = $sql->fetch()) + { + if ($row['user_name']) + { + $POSTER = "{$row['user_name']}"; + } + else + { + $POSTER = $row['thread_user_anon']; + } + + $LINKTOTHREAD = e107::getUrl()->create('forum/thread/view', array('id' =>$row['thread_id'])); //$e107->url->getUrl('forum', 'thread', "func=view&id={$row['thread_id']}"); + $LINKTOFORUM = e107::getUrl()->create('forum/forum/view', array('id' => $row['thread_forum_id'])); //$e107->url->getUrl('forum', 'forum', "func=view&id={$row['thread_forum_id']}"); + + $lastpost_datestamp = $gen->convert_date($row['thread_lastpost'], 'forum'); + if ($row['user_last']) + { + $LASTPOST = "{$row['user_last']}
    ".$lastpost_datestamp; + } + else + { + $LASTPOST = $row['thread_lastuser_anon'].'
    '.$lastpost_datestamp; + } + + $text .= " + + + + + + + \n"; + } + + $text .= "
     ".LAN_1."".LAN_2."".LAN_3."".LAN_4."".LAN_5."
    {$row['thread_name']} ({$row['forum_name']}){$POSTER}{$row['thread_views']}{$row['thread_total_replies']}{$LASTPOST}
    \n
    "; + + $ftotal = $sql->db_Count('forum_thread', '(*)', 'WHERE `thread_parent` = 0'); + $parms = "{$ftotal},{$view},{$from},".e_SELF.'?[FROM].active.forum.'.$view; + $text .= "
    ".$tp->parseTemplate("{NEXTPREV={$parms}}").'
    '; + $ns->tablerender(LAN_7, $text, 'nfp'); + /* + require_once (e_HANDLER.'np_class.php'); + $ftotal = $sql->db_Count('forum_thread', '(*)', 'WHERE 1'); + $ix = new nextprev('top.php', $from, $view, $ftotal, '', 'active.forum.'.$view); + */ + } +} +if ($action == 'top') +{ + //require_once (e_HANDLER.'level_handler.php'); + $rank = e107::getRank(); + + define('IMAGE_rank_main_admin_image', ($pref['rank_main_admin_image'] && file_exists(THEME."forum/".$pref['rank_main_admin_image']) ? "" : "")); + define('IMAGE_rank_admin_image', ($pref['rank_admin_image'] && file_exists(THEME."forum/".$pref['rank_admin_image']) ? "" : "")); + define('IMAGE_rank_moderator_image', ($pref['rank_moderator_image'] && file_exists(THEME."forum/".$pref['rank_moderator_image']) ? "" : "")); + + if ($subaction == 'forum' || $subaction == 'all') + { + require_once (e_PLUGIN.'forum/forum_class.php'); + $forum = new e107forum(); + + $qry = " + SELECT ue.*, u.* FROM `#user_extended` AS ue + LEFT JOIN `#user` AS u ON u.user_id = ue.user_extended_id + WHERE ue.user_plugin_forum_posts > 0 + ORDER BY ue.user_plugin_forum_posts DESC LIMIT {$from}, {$view} + "; + // $top_forum_posters = $sql->db_Select("user", "*", "`user_forums` > 0 ORDER BY user_forums DESC LIMIT ".$from.", ".$view.""); + $text = " +
    + + + + + + + \n"; + $counter = 1 + $from; + $sql2 = e107::getDb('sql2'); + if ($sql2->gen($qry)) + { + while ($row = $sql2->fetch()) + { + //$ldata = get_level($row['user_id'], $row['user_plugin_forum_posts'], $row['user_comments'], $row['user_chats'], $row['user_visits'], $row['user_join'], $row['user_admin'], $row['user_perms'], $pref); + $ldata = $rank->getRanks($row, (USER && $forum->isModerator(USERID))); + + if(vartrue($ldata['special'])) + { + $r = $ldata['special']; + } + else + { + $r = $ldata['pic'] ? $ldata['pic'] : defset($ldata['name'], $ldata['name']); + } + if(!$r) $r = 'n/a'; + $text .= " + + + + + "; + $counter++; + } + } + $text .= "
     ".TOP_LAN_1."".TOP_LAN_2."".TOP_LAN_6."
    {$counter}{$row['user_name']}{$row['user_plugin_forum_posts']}{$r}
    \n
    "; + if ($subaction == 'forum') + { + //$ftotal = $sql->db_Count('user', '(*)', 'WHERE `user_forums` > 0'); + $ftotal = $sql->count('user_extended', '(*)', 'WHERE `user_plugin_forum_posts` > 0'); + $parms = "{$ftotal},{$view},{$from},".e_SELF.'?[FROM].top.forum.'.$view; + $text .= "
    ".$tp->parseTemplate("{NEXTPREV={$parms}}").'
    '; + } + $ns->tablerender(TOP_LAN_0, $text); + /* + if ($subaction == 'forum') + { + require_once (e_HANDLER.'np_class.php'); + $ftotal = $sql->db_Count('user_extended', '(*)', 'WHERE `user_plugin_forum_posts` > 0'); + $ix = new nextprev('top.php', $from, $view, $ftotal, 'Forum Posts', 'top.forum.'.$view); + }*/ + } + + + if ($subaction == 'comment' || $subaction == 'all') + { + $top_forum_posters = $sql->select("user", "*", "`user_comments` > 0 ORDER BY user_comments DESC LIMIT 0, 10"); + $text = " +
    + + + + + + + \n"; + $counter = 1; + if($top_forum_posters) + { + while ($row = $sql->fetch()) + { + // TODO - Custom ranking (comments), LANs + $ldata = $rank->getRanks($row); + if(vartrue($ldata['special'])) + { + $r = $ldata['special']; + } + else + { + $r = $ldata['pic'] ? $ldata['pic'] : defset($ldata['name'], $ldata['name']); + } + if(!$r) $r = 'n/a'; + $text .= " + + + + + "; + $counter++; + } + } + else + { + $text .= " + + + "; + } + $text .= "
     ".TOP_LAN_1."".LAN_COMMENTS."".TOP_LAN_6."
    {$counter}{$row['user_name']}{$row['user_comments']}{$r}
    No results
    \n
    "; + $ns->tablerender(TOP_LAN_3, $text); + } + + if ($subaction == 'chat' || $subaction == 'all') + { + $top_forum_posters = $sql->select("user", "*", "`user_chats` > 0 ORDER BY user_chats DESC LIMIT 0, 10"); + $text = " +
    + + + + + + + \n"; + $counter = 1; + if($top_forum_posters) + { + while ($row = $sql->fetch()) + { + // TODO - Custom ranking (chat), LANs + $ldata = $rank->getRanks($row); + if(vartrue($ldata['special'])) + { + $r = $ldata['special']; + } + else + { + $r = $ldata['pic'] ? $ldata['pic'] : defset($ldata['name'], $ldata['name']); + } + if(!$r) $r = 'n/a'; + $text .= " + + + + + "; + $counter++; + } + + } + else + { + $text .= " + + + "; + } + $text .= "
     ".TOP_LAN_1."".TOP_LAN_2."".TOP_LAN_6."
    {$counter}{$row['user_name']}{$row['user_chats']}{$r}
    No results
    \n
    "; + $ns->tablerender(TOP_LAN_5, $text); + } +} +require_once(FOOTERF); ?> \ No newline at end of file