From: sakamocchi Date: Mon, 17 Sep 2012 11:10:23 +0000 (+0900) Subject: Merge branch 'skinnable-master' X-Git-Url: http://git.osdn.net/view?p=nucleus-jp%2Fnucleus-next.git;a=commitdiff_plain;h=c90b0980cfa3e79cd4bc7eed551a64a5e2b02a5c;hp=-c Merge branch 'skinnable-master' Conflicts: action.php index.php install/index.php nucleus/bookmarklet.php nucleus/convert/functions.inc.php nucleus/convert/wordpress.php nucleus/index.php nucleus/libs/ACTION.php nucleus/libs/ACTIONLOG.php nucleus/libs/ACTIONS.php nucleus/libs/ADMIN.php nucleus/libs/BAN.php nucleus/libs/BLOG.php nucleus/libs/BODYACTIONS.php nucleus/libs/BaseActions.php nucleus/libs/COMMENT.php nucleus/libs/COMMENTACTIONS.php nucleus/libs/COMMENTS.php nucleus/libs/ITEM.php nucleus/libs/ITEMACTIONS.php nucleus/libs/KARMA.php nucleus/libs/MANAGER.php nucleus/libs/MEDIA.php nucleus/libs/MEMBER.php nucleus/libs/NOTIFICATION.php nucleus/libs/PAGEFACTORY.php nucleus/libs/PARSER.php nucleus/libs/PLUGIN.php nucleus/libs/PLUGINADMIN.php nucleus/libs/SEARCH.php nucleus/libs/SKIN.php nucleus/libs/TEMPLATE.php nucleus/libs/backup.php nucleus/libs/globalfunctions.php nucleus/libs/i18n.php nucleus/libs/include/admin-add.template nucleus/libs/include/admin-edit.template nucleus/libs/include/bookmarklet-add.template nucleus/libs/include/bookmarklet-edit.template nucleus/libs/showlist.php nucleus/libs/skinie.php nucleus/libs/sql/DB.php nucleus/libs/sql/MYSQLPDO.php nucleus/libs/sql/sql.php nucleus/locales/bg_Cyrl_BG.ISO-8859-5.php nucleus/locales/bg_Cyrl_BG.UTF-8.php nucleus/locales/ca_Latn_ES.ISO-8859-1.php nucleus/locales/ca_Latn_ES.UTF-8.php nucleus/locales/cs_Latn_CZ.UTF-8.php nucleus/locales/cs_Latn_CZ.WINDOWS-1250.php nucleus/locales/de_Latn_DE.ISO-8859-1.php nucleus/locales/de_Latn_DE.UTF-8.php nucleus/locales/en_Latn_US.ISO-8859-1.php nucleus/locales/en_Latn_US.UTF-8.php nucleus/locales/es_Latn_ES.ISO-8859-1.php nucleus/locales/es_Latn_ES.UTF-8.php nucleus/locales/fa_Arab_IR.UTF-8.php nucleus/locales/fi_Latn_FI.ISO-8859-1.php nucleus/locales/fi_Latn_FI.UTF-8.php nucleus/locales/fr_Latn_FR.ISO-8859-15.php nucleus/locales/fr_Latn_FR.UTF-8.php nucleus/locales/gl_Latn_ES.ISO-8859-1.php nucleus/locales/gl_Latn_ES.UTF-8.php nucleus/locales/hr_Latn_HR.UTF-8.php nucleus/locales/hr_Latn_HR.WINDOWS-1250.php nucleus/locales/hu_Latn_HU.ISO-8859-2.php nucleus/locales/hu_Latn_HU.UTF-8.php nucleus/locales/id_Latn_ID.ISO-8859-1.php nucleus/locales/id_Latn_ID.UTF-8.php nucleus/locales/it_Latn_IT.ISO-8859-1.php nucleus/locales/it_Latn_IT.UTF-8.php nucleus/locales/ja_Jpan_JP.EUC-JP.php nucleus/locales/ja_Jpan_JP.UTF-8.php nucleus/locales/ko_Kore_KR.EUC-KR.php nucleus/locales/ko_Kore_KR.UTF-8.php nucleus/locales/ku_Arab_TR.UTF-8.php nucleus/locales/lv_Latn_LV.ISO-8859-13.php nucleus/locales/lv_Latn_LV.UTF-8.php nucleus/locales/nl_Latn_NL.ISO-8859-15.php nucleus/locales/nl_Latn_NL.UTF-8.php nucleus/locales/pl_Latn_PL.UTF-8.php nucleus/locales/pt_Latn_BR.ISO-8859-1.php nucleus/locales/pt_Latn_BR.UTF-8.php nucleus/locales/ro_Latn_RO.ISO-8859-1.php nucleus/locales/ro_Latn_RO.UTF-8.php nucleus/locales/ru_Cyrl_RU.UTF-8.php nucleus/locales/ru_Cyrl_RU.WINDOWS-1251.php nucleus/locales/sk_Latn_SK.ISO-8859-2.php nucleus/locales/sk_Latn_SK.UTF-8.php nucleus/locales/sr_Cyrl_RS.UTF-8.php nucleus/locales/ur_Arab_PK.UTF-8.php nucleus/locales/vi_Latn_VN.UTF-8.php nucleus/locales/zh_Hans_CN.GB2312.php nucleus/locales/zh_Hans_CN.UTF-8.php nucleus/locales/zh_Hant_TW.UTF-8.php nucleus/media.php nucleus/plugins/NP_SecurityEnforcer.php nucleus/plugins/NP_SkinFiles.php nucleus/upgrades/upgrade.functions.php nucleus/upgrades/upgrade4.0.php nucleus/xmlrpc/server.php skins/admin/bookmarklet/styles/addedit.css skins/default/nicetitle.js --- c90b0980cfa3e79cd4bc7eed551a64a5e2b02a5c diff --combined .buildpath index 0000000,0000000..8bcb4b5 new file mode 100644 --- /dev/null +++ b/.buildpath @@@ -1,0 -1,0 +1,5 @@@ ++ ++ ++ ++ ++ diff --combined .project index 0000000,0000000..7e1a46c new file mode 100644 --- /dev/null +++ b/.project @@@ -1,0 -1,0 +1,22 @@@ ++ ++ ++ nucleus-next ++ ++ ++ ++ ++ ++ org.eclipse.wst.validation.validationbuilder ++ ++ ++ ++ ++ org.eclipse.dltk.core.scriptbuilder ++ ++ ++ ++ ++ ++ org.eclipse.php.core.PHPNature ++ ++ diff --combined .settings/org.eclipse.core.resources.prefs index 0000000,0000000..730e5d2 new file mode 100644 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@@ -1,0 -1,0 +1,24 @@@ ++eclipse.preferences.version=1 ++encoding//nucleus/locales/bg_Cyrl_BG.ISO-8859-5.php=ISO-8859-5 ++encoding//nucleus/locales/ca_Latn_ES.ISO-8859-1.php=ISO-8859-1 ++encoding//nucleus/locales/cs_Latn_CZ.WINDOWS-1250.php=WINDOWS-1250 ++encoding//nucleus/locales/de_Latn_DE.ISO-8859-1.php=ISO-8859-1 ++encoding//nucleus/locales/el_Grek_GR.WINDOWS-1253.php=WINDOWS-1253 ++encoding//nucleus/locales/en_Latn_US.ISO-8859-1.php=ISO-8859-1 ++encoding//nucleus/locales/es_Latn_ES.ISO-8859-1.php=ISO-8859-1 ++encoding//nucleus/locales/fi_Latn_FI.ISO-8859-1.php=ISO-8859-1 ++encoding//nucleus/locales/fr_Latn_FR.ISO-8859-15.php=ISO-8859-15 ++encoding//nucleus/locales/gl_Latn_ES.ISO-8859-1.php=ISO-8859-1 ++encoding//nucleus/locales/hr_Latn_HR.WINDOWS-1250.php=WINDOWS-1250 ++encoding//nucleus/locales/hu_Latn_HU.ISO-8859-2.php=ISO-8859-2 ++encoding//nucleus/locales/id_Latn_ID.ISO-8859-1.php=ISO-8859-1 ++encoding//nucleus/locales/it_Latn_IT.ISO-8859-1.php=ISO-8859-1 ++encoding//nucleus/locales/ja_Jpan_JP.EUC-JP.php=EUC-JP ++encoding//nucleus/locales/ko_Kore_KR.EUC-KR.php=EUC-KR ++encoding//nucleus/locales/lv_Latn_LV.ISO-8859-13.php=ISO-8859-13 ++encoding//nucleus/locales/nl_Latn_NL.ISO-8859-15.php=ISO-8859-15 ++encoding//nucleus/locales/pt_Latn_BR.ISO-8859-1.php=ISO-8859-1 ++encoding//nucleus/locales/ro_Latn_RO.ISO-8859-1.php=ISO-8859-1 ++encoding//nucleus/locales/ru_Cyrl_RU.WINDOWS-1251.php=WINDOWS-1251 ++encoding//nucleus/locales/sk_Latn_SK.ISO-8859-2.php=ISO-8859-2 ++encoding//nucleus/locales/zh_Hans_CN.GB2312.php=GB2312 diff --combined .settings/org.eclipse.php.core.prefs index 0000000,0000000..5f7d896 new file mode 100644 --- /dev/null +++ b/.settings/org.eclipse.php.core.prefs @@@ -1,0 -1,0 +1,2 @@@ ++eclipse.preferences.version=1 ++include_path= diff --combined action.php index 6cf854a,56d18a8..33529ec --- a/action.php +++ b/action.php @@@ -1,35 -1,35 +1,72 @@@ ++<<<<<<< HEAD +doAction($action); + +if ( $errorInfo ) +{ + $skin = new SKIN($errorInfo['skinid']); + doError($errorInfo['message'], $skin); +} + ++======= + doAction($action); + + if ( $errorInfo ) + { + $skin =& $manager->getSkin($errorInfo['skinid']); + doError($errorInfo['message'], $skin); + } + ++>>>>>>> skinnable-master exit; diff --combined index.php index 3440faf,e824f67..17c1577 --- a/index.php +++ b/index.php @@@ -1,8 -1,9 +1,20 @@@ ++<<<<<<< HEAD +>>>>>> skinnable-master diff --combined install/index.php index 17fb9a3,04288ee..13fd7be --- a/install/index.php +++ b/install/index.php @@@ -1,1726 -1,1817 +1,3546 @@@ ++<<<<<<< HEAD + Nucleus requires at least PHP version ' . $minimum_php_version . ''); +} + +// make sure there's no unnecessary escaping: # set_magic_quotes_runtime(0); +if ( version_compare(PHP_VERSION, '5.3.0', '<') ) +{ + ini_set('magic_quotes_runtime', '0'); +} + +/* default installed plugins and skins */ +$aConfPlugsToInstall = array('NP_SecurityEnforcer', 'NP_SkinFiles'); +$aConfSkinsToImport = array('atom', 'rss2.0', 'rsd', 'default'); + +// Check if some important files +do_check_files(); + +/* i18n class is needed for internationalization */ +include_once('../nucleus/libs/i18n.php'); +if ( !i18n::init('UTF-8', '../nucleus/locales') ) +{ + exit('
Failed to initialize iconv or mbstring extension. Would you please contact the administrator of your PHP server?
'); +} + +// include core classes that are needed for login & plugin handling + +// added for 3.5 sql_* wrapper +global $MYSQL_HANDLER; + +if ( !isset($MYSQL_HANDLER) ) +{ + $MYSQL_HANDLER = array('mysql', ''); + + // check if mysql support is installed; this check may not make sense, as is, in a version past 3.5x + if ( !function_exists('mysql_query') && !function_exists('mysqli_query') ) + { + exit('
Your PHP version does not have support for MySQL :(
'); + } +} +include_once('../nucleus/libs/sql/sql.php'); + +session_start(); +if ( count($_GET) == 0 && count($_POST) == 0 ) +{ + unset($_SESSION['param_manager']); +} + +// restore the $param from the session +if ( array_key_exists('param_manager', $_SESSION) ) +{ + $param = $_SESSION['param_manager']; +} +else +{ + $param = new ParamManager(); +} + +// include translation file +if ( array_key_exists('locale', $_POST) ) $param->set_locale(); +i18n::set_current_locale($param->locale); +$translation_file = './locales/' . i18n::get_current_locale() . '.' . i18n::get_current_charset() . '.php'; +if ( !file_exists($translation_file) ) +{ + $translation_file = './locales/en_Latn_US.UTF-8.php'; +} +include($translation_file); + +do_action(); + +// $param is saved to the session +if ( isset($param) ) +{ + $_SESSION['param_manager'] = $param; +} +else +{ + unset($_SESSION['param_manager']); +} +exit; + +/** + * installer action + */ +function do_action() +{ + global $param; + + if ( array_key_exists('action', $_POST) ) + { + $isPostback = true; + } + else + { + $isPostback = false; + } + + // mode change + if ( array_key_exists('mode', $_REQUEST) ) + { + if ( $_REQUEST['mode'] == 'detail' ) + { + $param->set_state('detail'); + } + elseif ( $_REQUEST['mode'] == 'simple' ) + { + $param->set_state('mysql'); + } + } + + // input parameter check + if ( $isPostback ) + { + switch ( $param->state ) + { + case 'locale': + $param->set_locale(); + $param->set_state('mysql'); + $isPostback = false; + break; + case 'mysql': + if ( count($param->check_mysql_parameters()) == 0 ) + { + $param->set_state('weblog'); + $isPostback = false; + } + break; + case 'weblog': + if ( count($param->check_user_parameters()) == 0 + && count($param->check_weblog_parameters()) == 0 ) + { + $param->set_state('install'); + $isPostback = false; + } + break; + case 'detail': + if ( $param->check_all_parameters() ) + { + $param->set_state('install'); + $isPostback = false; + } + break; + } + } + + // page render + show_header(); + switch ( $param->state ) + { + case 'locale': + show_select_locale_form(); + break; + case 'mysql': + show_database_setting_form($isPostback); + break; + case 'weblog': + show_blog_setting_form($isPostback); + break; + case 'detail': + show_detail_setting_form($isPostback); + break; + case 'install': + show_install_complete_form(); + break; + } + show_footer(); +} + +/** + * header tag of the installation screens + **/ +function show_header() +{ + global $param; + + /* HTTP 1.1 application for no caching */ + header("Cache-Control: no-cache, must-revalidate"); + header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); + header('Content-Type: text/html; charset=' . i18n::get_current_charset()); +?> + + + + <?php echo _TITLE; ?> + + + + + + + + + + + +
+

+ Select your locale: +

+
+ +
+ +

Nucleus is installed in the selected locale, the locale of the Asterisk prefixed will be displayed in English because there is no translation of the installer file.

+

We will wait for the translator by volunteers!

+

+

+ +

+
+
+
+ +
+

+', $config_writable, ''; + } + if ( $mysql_version == '0.0.0' ) + { + echo '', _DBVERSION_UNKOWN, ''; + } + elseif ( version_compare($mysql_version, $minimum_mysql_version, '<') ) + { + echo '', sprintf(_DBVERSION_TOOLOW, $minimum_mysql_version), ''; + } +?> +

+
+
+

+

+check_mysql_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } +?> +

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

+ + +

+

+ +

+
+
+
+ +
+

+ +

+
+
+

+

+check_weblog_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } +?> +

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

+

+check_user_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } +?> +

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

+ +

+
+
+
+ +
+

+ +check_all_parameters() ) + { + echo '', _VALID_ERROR, "\n"; + } +?> +

+ +
+ +
+

+

+check_mysql_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } +?> +

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

+

+check_uri_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + $errors = $param->check_path_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } +?> +

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

+ +

+ +

+

+check_user_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } +?> +

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

+

+check_weblog_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } +?> +

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

+ +

+ +

+ +

+
+
+
+ +
+

+ 0 ) + { + echo _INST_ERROR; + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + else + { + echo _INST_TEXT; + if ( array_key_exists('config_data', $_SESSION) ) + { + echo '', _INST_TEXT4, ''; +?> + +', _INST_TEXT5, ''; + } +?> +

+
+
+

+

+ blog_name); ?> +

+

+ +

+
+ +
+

+

+ +

+

+ +

+
+ +
+

+

+ +

+

+ +

+
+
+ +
+mysql_host; + $MYSQL_USER = $param->mysql_user; + $MYSQL_PASSWORD = $param->mysql_password; + $MYSQL_DATABASE = $param->mysql_database; + $MYSQL_PREFIX = $param->mysql_tablePrefix; + + $DIR_NUCLEUS = $param->AdminPath; + $DIR_MEDIA = $param->MediaPath; + $DIR_SKINS = $param->SkinsPath; + $DIR_PLUGINS = $DIR_NUCLEUS . 'plugins/'; + $DIR_LOCALES = $DIR_NUCLEUS . 'locales/'; + $DIR_LIBS = $DIR_NUCLEUS . 'libs/'; + + /* + * 2.open mySQL connection + */ + $MYSQL_CONN = @DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD); + if ( $MYSQL_CONN == FALSE ) + { + $errors[] = _DBCONNECT_ERROR; + return $errors; + } + + /* + * 3. try to create database if needed + */ + if ( DB::execute("CREATE DATABASE IF NOT EXISTS {$MYSQL_DATABASE}") === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR1 . ': ' . $errinfo[2]; + } + + /* + * 4. try to select database + */ + $MYSQL_CONN = @DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE); + if ( !$MYSQL_CONN ) + { + $errors[] = _INST_ERROR2; + } + + if ( count($errors) > 0 ) + { + return $errors; + } + + /* + * 5. execute queries + */ + $table_names = array( + 'nucleus_actionlog', + 'nucleus_ban', + 'nucleus_blog', + 'nucleus_category', + 'nucleus_comment', + 'nucleus_config', + 'nucleus_item', + 'nucleus_karma', + 'nucleus_member', + 'nucleus_plugin', + 'nucleus_skin', + 'nucleus_template', + 'nucleus_team', + 'nucleus_activation', + 'nucleus_tickets' + ); + + $prefixed_table_names = array(); + foreach ( $table_names as $table_name ) + { + $prefixed_table_names[] = $MYSQL_PREFIX . $table_name; + } + + // table exists check + $result = DB::getResult('SHOW TABLES'); + foreach ( $result as $row ) + { + if ( in_array($row[0], $prefixed_table_names) ) + { + $errors[] = _INST_ERROR3; + break; + } + } + if ( count($errors) > 0 ) + { + return $errors; + } + + $filename = 'install.sql'; + $fd = fopen($filename, 'r'); + $queries = fread($fd, filesize($filename)); + fclose($fd); + + $queries = preg_split('#(;\n|;\r)#', $queries); + + foreach ( $queries as $query ) + { + if ( preg_match('/\w+/', $query) ) + { + if ( $MYSQL_PREFIX ) + { + $query = str_replace($table_names, $prefixed_table_names, $query); + } + + if ( DB::execute($query) === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR4 . ' (' . $query . '): ' . $errinfo[2]; + } + } + } + + /* + * 6. put needed records + */ + /* push first post */ + $query = "INSERT INTO %s VALUES (1, %s, %s, %s, 1, 1, %s, 0, 0, 0, 1, 0, 1)"; + $query = sprintf($query, + tableName('nucleus_item'), + DB::quoteValue(_1ST_POST_TITLE), + DB::quoteValue(_1ST_POST), + DB::quoteValue(_1ST_POST2), + DB::formatDateTime() + ); + if ( DB::execute($query) === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR4 . ' (' . $query . '): ' . $errinfo[2]; + } + + /* push configurations */ + array_merge($errors, updateConfig('IndexURL', $param->IndexURL)); + array_merge($errors, updateConfig('AdminURL', $param->AdminURL)); + array_merge($errors, updateConfig('MediaURL', $param->MediaURL)); + array_merge($errors, updateConfig('SkinsURL', $param->SkinsURL)); + array_merge($errors, updateConfig('PluginURL', $param->PluginURL)); + array_merge($errors, updateConfig('ActionURL', $param->ActionURL)); + array_merge($errors, updateConfig('AdminEmail', $param->user_email)); + array_merge($errors, updateConfig('SiteName', $param->blog_name)); + array_merge($errors, updateConfig('Locale', i18n::get_current_locale())); + + /* push super admin */ + $query = "UPDATE %s SET mname = %s, mrealname = %s, mpassword = %s, memail = %s, murl = %s, madmin = 1, mcanlogin = 1 WHERE mnumber = 1"; + $query = sprintf($query, + tableName('nucleus_member'), + DB::quoteValue($param->user_name), + DB::quoteValue($param->user_realname), + DB::quoteValue(md5($param->user_password)), + DB::quoteValue($param->user_email), + DB::quoteValue($param->IndexURL) + ); + if ( DB::execute($query) === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR5 . ': ' . $errinfo[2]; + } + + /* push new weblog */ + $query = "UPDATE %s SET bname = %s, bshortname = %s, burl = %s WHERE bnumber = 1"; + $query = sprintf($query, + tableName('nucleus_blog'), + DB::quoteValue($param->blog_name), + DB::quoteValue($param->blog_shortname), + DB::quoteValue($param->IndexURL) + ); + if ( DB::execute($query) === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR6 . ': ' . $errinfo[2]; + } + + /* push default category */ + $query = "UPDATE %s SET cname = %s, cdesc = %s WHERE catid = 1"; + $query = sprintf($query, + tableName('nucleus_category'), + DB::quoteValue(_GENERALCAT_NAME), + DB::quoteValue(_GENERALCAT_DESC) + ); + if ( DB::execute($query) === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR6 . ': ' . $errinfo[2]; + } + + /* + * 7. install default plugins and skins + */ + global $aConfPlugsToInstall, $aConfSkinsToImport; + $aSkinErrors = array(); + $aPlugErrors = array(); + + if ( (count($aConfPlugsToInstall) > 0) || (count($aConfSkinsToImport) > 0) ) + { + include_once($DIR_LIBS . 'globalfunctions.php'); + global $manager; + if ( !isset($manager) ) + { + $manager = new Manager(); + } + + include_once($DIR_LIBS . 'skinie.php'); + + $aSkinErrors = installCustomSkins(); + if ( count($aSkinErrors) > 0 ) + { + array_merge($errors, $aSkinErrors); + } + + $query = "SELECT sdnumber FROM %s WHERE sdname='default'"; + $query = sprintf($query, tableName('nucleus_skin_desc')); + $defSkinID = intval(DB::getValue($query)); + + $query = "UPDATE %s SET bdefskin=%d WHERE bnumber=1"; + $query = sprintf($query, tableName('nucleus_blog'), $defSkinID); + DB::execute($query); + + $query = "UPDATE %s SET value=%d WHERE name='BaseSkin'"; + $query = sprintf($query, tableName('nucleus_config'), $defSkinID); + DB::execute($query); + + $aPlugErrors = installCustomPlugs(); + if ( count($aPlugErrors) > 0 ) + { + array_merge($errors, $aPlugErrors); + } + } + + /* + * 8. Write config file ourselves (if possible) + */ + $config_data = '<' . '?php' . "\n"; + $config_data .= "// mySQL connection information\n"; + $config_data .= "\$MYSQL_HOST = '" . $MYSQL_HOST . "';\n"; + $config_data .= "\$MYSQL_USER = '" . $MYSQL_USER . "';\n"; + $config_data .= "\$MYSQL_PASSWORD = '" . $MYSQL_PASSWORD . "';\n"; + $config_data .= "\$MYSQL_DATABASE = '" . $MYSQL_DATABASE . "';\n"; + $config_data .= "\$MYSQL_PREFIX = '" . $MYSQL_PREFIX . "';\n"; + $config_data .= "// new in 3.50. first element is db handler, the second is the db driver used by the handler\n"; + $config_data .= "// default is \$MYSQL_HANDLER = array('mysql','mysql');\n"; + $config_data .= "//\$MYSQL_HANDLER = array('mysql','mysql');\n"; + $config_data .= "//\$MYSQL_HANDLER = array('pdo','mysql');\n"; + $config_data .= "\$MYSQL_HANDLER = array('" . $MYSQL_HANDLER[0] . "','" . $MYSQL_HANDLER[1] . "');\n"; + $config_data .= "\n"; + $config_data .= "// main nucleus directory\n"; + $config_data .= "\$DIR_NUCLEUS = '" . $DIR_NUCLEUS . "';\n"; + $config_data .= "\n"; + $config_data .= "// path to media dir\n"; + $config_data .= "\$DIR_MEDIA = '" . $DIR_MEDIA . "';\n"; + $config_data .= "\n"; + $config_data .= "// extra skin files for imported skins\n"; + $config_data .= "\$DIR_SKINS = '" . $DIR_SKINS . "';\n"; + $config_data .= "\n"; + $config_data .= "// these dirs are normally sub dirs of the nucleus dir, but \n"; + $config_data .= "// you can redefine them if you wish\n"; + $config_data .= "\$DIR_PLUGINS = \$DIR_NUCLEUS . 'plugins/';\n"; + $config_data .= "\$DIR_LOCALES = \$DIR_NUCLEUS . 'locales/';\n"; + $config_data .= "\$DIR_LIBS = \$DIR_NUCLEUS . 'libs/';\n"; + $config_data .= "\n"; + $config_data .= "// include libs\n"; + $config_data .= "include(\$DIR_LIBS.'globalfunctions.php');\n"; + $config_data .= "?" . ">"; + + $result = false; + if ( @!file_exists('../config.php') || is_writable('../config.php') ) + { + if ( $fp = @fopen('../config.php', 'w') ) + { + $result = @fwrite($fp, $config_data, i18n::strlen($config_data)); + fclose($fp); + } + } + + if ( $result ) + { + // try to change the read-only permission. + if ( strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' ) + { + @chmod('../config.php', 0444); + } + } + else + { + $_SESSION['config_data'] = $config_data; + } + + return $errors; +} + +/** + * Confirm that you can write to the configuration file + * @return string error message + */ +function canConfigFileWritable() +{ + if ( @file_exists('../config.php') && @!is_writable('../config.php') ) + { + // try to change the read-write permission. + if ( strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' ) + { + @chmod('../config.php', 0666); + } + + if ( @!is_writable('../config.php') ) + { + return _INST_ERROR8; + } + } + return ''; +} + +/** + * To obtain the version of MySQL + * @return string + */ +function getMySqlVersion() +{ + global $MYSQL_HANDLER, $minimum_mysql_version, $errors; + // Turn on output buffer + // Needed to repress the output of the sql function that are + // not part of php (in this case the @ operator doesn't work) + ob_start(); + + // note: this piece of code is taken from phpMyAdmin + $conn = @DB::setConnectionInfo($MYSQL_HANDLER[1], 'localhost', '', ''); + + if ( $conn ) + { + $row = DB::getAttribute(PDO::ATTR_SERVER_VERSION); + $match = preg_split('#\.#', $row); + } + else + { + $row = @DB::getRow('SHOW VARIABLES LIKE \'version\''); + + if ( $row ) + { + $match = preg_split('#\.#', $row[1]); + } + else + { + $output = (function_exists('shell_exec')) ? @shell_exec('mysql -V') : '0.0.0'; + preg_match('@[0-9]+\.[0-9]+\.[0-9]+@', $output, $version); + $match = preg_split('#\.#', $version[0]); + + if ( $match[0] == '' ) + { + $match = array('0', '0', '0'); + } + } + } + + @DB::disConnect(); + + //End and clean output buffer + ob_end_clean(); + + return implode($match, '.'); +} + +/** + * Add a table prefix if it is used + * + * @param string $input table name with prefix + * @return string + */ +function tableName($input) +{ + global $MYSQL_PREFIX; + if ( $MYSQL_PREFIX ) + { + return $MYSQL_PREFIX . $input; + } + else + { + return $input; + } +} + +/** + * Install custom plugins + */ +function installCustomPlugs() +{ + global $aConfPlugsToInstall, $DIR_LIBS, $manager; + + $aErrors = array(); + if ( count($aConfPlugsToInstall) == 0 ) + { + return $aErrors; + } + + $query = sprintf('SELECT * FROM %s', tableName('nucleus_plugin')); + $res = DB::getResult($query); + $numCurrent = $res->rowCount(); + + foreach ( $aConfPlugsToInstall as $plugName ) + { + $query = sprintf('INSERT INTO %s (porder, pfile) VALUES (%d, %s)', + tableName('nucleus_plugin'), + (++$numCurrent), + DB::quoteValue($plugName)); + DB::execute($query); + + $manager->clearCachedInfo('installedPlugins'); + $plugin =& $manager->getPlugin($plugName); + $plugin->setID($numCurrent); + + if ( !$plugin ) + { + $query = sprintf('DELETE FROM %s WHERE pfile = %s', + tableName('nucleus_plugin'), + DB::quoteValue($plugName)); + DB::execute($query); + $numCurrent--; + array_push($aErrors, sprintf(_INST_ERROR9, $plugName)); + continue; + } + $plugin->install(); + } + + $query = sprintf('DELETE FROM %s', tableName('nucleus_plugin_event')); + DB::execute($query); + $query = sprintf('SELECT pid, pfile FROM %s', tableName('nucleus_plugin')); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $plug =& $manager->getPlugin($row['pfile']); + + if ( $plug ) + { + $eventList = $plug->getEventList(); + foreach ( $eventList as $eventName ) + { + $query = sprintf('INSERT INTO %s (pid, event) VALUES (%d, %s)', + tableName('nucleus_plugin_event'), + intval($row['pid']), + DB::quoteValue($eventName)); + DB::execute($query); + } + } + } + return $aErrors; +} + +/** + * Install custom skins + * Prepares the installation of custom skins + */ +function installCustomSkins() +{ + global $aConfSkinsToImport, $DIR_LIBS, $DIR_SKINS; + + $aErrors = array(); + if ( count($aConfSkinsToImport) == 0 ) + { + return $aErrors; + } + + $importer = new SkinImport(); + + foreach ( $aConfSkinsToImport as $skinName ) + { + $importer->reset(); + $skinFile = $DIR_SKINS . $skinName . '/skinbackup.xml'; + + if ( !@file_exists($skinFile) ) + { + array_push($aErrors, sprintf(_INST_ERROR10, $skinFile)); + continue; + } + + $error = $importer->readFile($skinFile); + + if ( $error ) + { + array_push($aErrors, sprintf(_INST_ERROR11, $skinName) . ' : ' . $error); + continue; + } + + $error = $importer->writeToDatabase(1); + + if ( $error ) + { + array_push($aErrors, sprintf(_INST_ERROR12, $skinName) . ' : ' . $error); + continue; + } + } + return $aErrors; +} + +/** + * Check if some important files of the Nucleus CMS installation are available + * Give an error if one or more files are not accessible + */ +function do_check_files() +{ + $missingfiles = array(); + $files = array( + './install.sql', + '../index.php', + '../action.php', + '../nucleus/index.php', + '../nucleus/media.php', + '../nucleus/libs/ACTION.php', + '../nucleus/libs/ACTIONLOG.php', + '../nucleus/libs/ACTIONS.php', + '../nucleus/libs/ADMIN.php', + '../nucleus/libs/BaseActions.php', + '../nucleus/libs/BLOG.php', + '../nucleus/libs/BODYACTIONS.php', + '../nucleus/libs/COMMENT.php', + '../nucleus/libs/COMMENTACTIONS.php', + '../nucleus/libs/COMMENTS.php', + '../nucleus/libs/ENCAPSULATE.php', + '../nucleus/libs/ENTITY.php', + '../nucleus/libs/globalfunctions.php', + '../nucleus/libs/i18n.php', + '../nucleus/libs/ITEM.php', + '../nucleus/libs/ITEMACTIONS.php', + '../nucleus/libs/LINK.php', + '../nucleus/libs/MANAGER.php', + '../nucleus/libs/MEDIA.php', + '../nucleus/libs/MEMBER.php', + '../nucleus/libs/NOTIFICATION.php', + '../nucleus/libs/PAGEFACTORY.php', + '../nucleus/libs/PARSER.php', + '../nucleus/libs/PLUGIN.php', + '../nucleus/libs/PLUGINADMIN.php', + '../nucleus/libs/SEARCH.php', + '../nucleus/libs/showlist.php', + '../nucleus/libs/SKIN.php', + '../nucleus/libs/TEMPLATE.php', + '../nucleus/libs/vars4.1.0.php', + '../nucleus/libs/xmlrpc.inc.php', + '../nucleus/libs/xmlrpcs.inc.php', + '../nucleus/libs/sql/DB.php', + '../nucleus/libs/sql/MYSQLPDO.php' + ); + + $count = count($files); + for ( $i = 0; $i < $count; $i++ ) + { + if ( !is_readable($files[$i]) ) + { + array_push($missingfiles, 'File ' . $files[$i] . ' is missing or not readable.
'); + } + } + + if ( count($missingfiles) > 0 ) + { + exit(implode("\n", $missingfiles)); + } +} + +/** + * Updates the configuration in the database + * + * @param string $name name of the config var + * @param string $value new value of the config var + * @return array + */ +function updateConfig($name, $value) +{ + $errors = array(); + + $query = "UPDATE %s SET value = %s WHERE name = %s"; + $query = sprintf($query, tableName('nucleus_config'), DB::quoteValue(trim($value)), DB::quoteValue($name)); + + if ( DB::execute($query) === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR4 . ': ' . $errinfo[2]; + } + return $errors; +} + +class ParamManager +{ + /* process parameter */ + public $state; + public $locale; + + /* mysql connection parameters */ + public $mysql_host; + public $mysql_user; + public $mysql_password; + public $mysql_database; + public $mysql_tablePrefix; + + /* weblog configuration parameters */ + public $blog_name; + public $blog_shortname; + + /* member configuration parameters */ + public $user_name; + public $user_realname; + public $user_password; + private $user_password2; + public $user_email; + + /* URI parameters */ + private $root_url; + public $IndexURL; + public $AdminURL; + public $MediaURL; + public $SkinsURL; + public $PluginURL; + public $ActionURL; + + /* path parameters */ + private $root_path; + public $AdminPath; + public $MediaPath; + public $SkinsPath; + + /** + * constructor + */ + public function __construct() + { + $this->init(); + } + + public function init() + { + // set default values + $this->state = 'locale'; + $this->install_mode = 'simple'; + $this->locale = 'en_Latn_US'; + $this->mysql_host = @ini_get('mysql.default_host'); + $this->blog_name = 'My Nucleus CMS'; + $this->blog_shortname = 'mynucleuscms'; + + /* root path */ + $directory_separator = preg_quote(DIRECTORY_SEPARATOR, '|'); + $this->root_path = implode('/', preg_split("|$directory_separator|", realpath(dirname(__FILE__) . '/..'))); + if ( substr($this->root_path, -1, 1) !== '/' ) + { + $this->root_path .= '/'; + } + $base_path_pcre = preg_quote($this->root_path, '|'); + + /* current directry name */ + $directory_name = preg_replace("#{$base_path_pcre}#", '', implode('/', preg_split("#{$directory_separator}#", realpath(dirname(__FILE__))))); + $directory_name_pcre = preg_quote($directory_name, '|'); + + /* root uri */ + $root_url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']; + $this->root_url = preg_replace("|$directory_name_pcre(.*)$|", '', $root_url); + + $this->AdminPath = $this->root_path . 'nucleus/'; + $this->MediaPath = $this->root_path . 'media/'; + $this->SkinsPath = $this->root_path . 'skins/'; + + $this->IndexURL = $this->root_url; + $this->AdminURL = $this->root_url . 'nucleus/'; + $this->MediaURL = $this->root_url . 'media/'; + $this->SkinsURL = $this->root_url . 'skins/'; + $this->PluginURL = $this->root_url . 'nucleus/plugins/'; + $this->ActionURL = $this->root_url . 'action.php'; + } + + private function read_parameter($parameter) + { + foreach ( $parameter as $element ) + { + if ( array_key_exists($element, $_POST) ) + { + $this->$element = $_POST[$element]; + } + } + } + + public function set_state($state) + { + $states = array('locale', 'mysql', 'weblog', 'detail', 'install'); + if ( in_array($state, $states) ) + { + $this->state = $state; + } + } + + public function set_locale() + { + $this->read_parameter(array('locale')); + + if ( !in_array($this->locale, i18n::get_available_locale_list()) ) + { + $this->locale = 'en_Latn_US'; + } + } + + public function check_mysql_parameters() + { + global $MYSQL_HANDLER; + + $parameters = array('mysql_host', 'mysql_user', 'mysql_password', 'mysql_database', 'mysql_tablePrefix'); + $this->read_parameter($parameters); + + $errors = array(); + if ( $this->mysql_host == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _DB_FIELD1); + } + + if ( $this->mysql_user == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _DB_FIELD2); + } + + if ( $this->mysql_user != '' + && !preg_match('/^[a-z0-9_\-]+$/i', $this->mysql_user) ) + { + $errors[] = sprintf(_VALID_ERROR2, _DB_FIELD2); + } + + if ( $this->mysql_database == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _DB_FIELD4); + } + + if ( $this->mysql_database != '' + && !preg_match('/^[a-z0-9_\-]+$/i', $this->mysql_database) ) + { + $errors[] = sprintf(_VALID_ERROR2, _DB_FIELD4); + } + + if ( $this->mysql_tablePrefix != '' + && !preg_match('/^[a-z0-9_]+$/i', $this->mysql_tablePrefix) ) + { + $errors[] = sprintf(_VALID_ERROR3, _DB_FIELD5); + } + + if ( count($errors) == 0 ) + { + $mysql_conn = @DB::setConnectionInfo($MYSQL_HANDLER[1], $this->mysql_host, $this->mysql_user, $this->mysql_password); + if ( $mysql_conn == false ) + { + $errors[] = _DBCONNECT_ERROR; + } + else + { + @DB::disConnect(); + } + } + + return $errors; + } + + public function check_user_parameters() + { + $parameters = array('user_name', 'user_realname', 'user_password', 'user_password2', 'user_email'); + $this->read_parameter($parameters); + + $errors = array(); + if ( $this->user_realname == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _ADMIN_FIELD1); + } + + if ( $this->user_name == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _ADMIN_FIELD2); + } + elseif ( !preg_match("/^[a-z0-9]+([ a-z0-9]*[a-z0-9]+)?$/i", $this->user_name) ) + { + $errors[] = _VALID_ERROR5; + } + + if ( $this->user_password == '' || $this->user_password2 == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _ADMIN_FIELD3); + $this->user_password = ''; + } + elseif ( $this->user_password != $this->user_password2 ) + { + $errors[] = _VALID_ERROR6; + $this->user_password = ''; + } + + if ( !preg_match("/^[a-z0-9\._+\-]+@[a-z0-9\._\-]+\.[a-z]{2,6}$/i", $this->user_email) ) + { + $errors[] = _VALID_ERROR7; + } + + return $errors; + } + + public function check_weblog_parameters() + { + $parameters = array('blog_name', 'blog_shortname'); + $this->read_parameter($parameters); + + $errors = array(); + if ( $this->blog_name == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _BLOG_FIELD1); + } + + if ( $this->blog_shortname == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _BLOG_FIELD2); + } + + if ( !preg_match("/^[a-z0-9]+$/i", $this->blog_shortname) ) + { + $errors[] = _VALID_ERROR4; + } + + return $errors; + } + + public function check_uri_parameters() + { + $parameters = array('IndexURL', 'AdminURL', 'MediaURL', 'SkinsURL', 'PluginURL', 'ActionURL'); + $this->read_parameter($parameters); + + $errors = array(); + if ( substr($this->IndexURL, -1, 1) !== '/' ) + { + $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD1); + } + + if ( substr($this->AdminURL, -1, 1) !== '/' ) + { + $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD2); + } + + if ( substr($this->MediaURL, -1, 1) !== '/' ) + { + $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD4); + } + + if ( substr($this->SkinsURL, -1, 1) !== '/' ) + { + $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD6); + } + + if ( substr($this->PluginURL, -1, 1) !== '/' ) + { + $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD8); + } + + if ( strrchr($this->ActionURL, '/') != '/action.php' ) + { + $errors[] = sprintf(_VALID_ERROR9, _PATH_FIELD9); + } + + return $errors; + } + + public function check_path_parameters() + { + $parameters = array('AdminPath', 'MediaPath', 'SkinsPath'); + $this->read_parameter($parameters); + + $separators = array('/', DIRECTORY_SEPARATOR); + $errors = array(); + if ( !in_array(substr($this->AdminPath, -1, 1), $separators) ) + { + $errors[] = sprintf(_VALID_ERROR10, _PATH_FIELD3); + } + elseif ( !file_exists($this->AdminPath) ) + { + $errors[] = sprintf(_VALID_ERROR11, _PATH_FIELD3); + } + + if ( !in_array(substr($this->MediaPath, -1, 1), $separators) ) + { + $errors[] = sprintf(_VALID_ERROR10, _PATH_FIELD5); + } + elseif ( !file_exists($this->MediaPath) ) + { + $errors[] = sprintf(_VALID_ERROR11, _PATH_FIELD5); + } + + if ( !in_array(substr($this->SkinsPath, -1, 1), $separators) ) + { + $errors[] = sprintf(_VALID_ERROR10, _PATH_FIELD7); + } + elseif ( !file_exists($this->SkinsPath) ) + { + $errors[] = sprintf(_VALID_ERROR11, _PATH_FIELD7); + } + + return $errors; + } + + /** + * check all parameters + * @return bool + */ + public function check_all_parameters() + { + $this->set_locale(); + + $isValid = true; + $isValid &= (count($this->check_mysql_parameters()) == 0); + $isValid &= (count($this->check_user_parameters()) == 0); + $isValid &= (count($this->check_weblog_parameters()) == 0); + $isValid &= (count($this->check_uri_parameters()) == 0); + $isValid &= (count($this->check_path_parameters()) == 0); + + return $isValid; + } +} ++======= + Nucleus requires at least PHP version ' . $minimum_php_version . ''); + } + + // make sure there's no unnecessary escaping: # set_magic_quotes_runtime(0); + if ( version_compare(PHP_VERSION, '5.3.0', '<') ) + { + ini_set('magic_quotes_runtime', '0'); + } + + /* default installed plugins and skins */ + $aConfPlugsToInstall = array('NP_SecurityEnforcer', 'NP_SkinFiles', 'NP_Medium'); + $aConfSkinsToImport = array('atom', 'rss2.0', 'rsd', 'default', 'admin/default', 'admin/bookmarklet'); + + // Check if some important files + do_check_files(); + + /* i18n class is needed for internationalization */ + include_once('../nucleus/libs/i18n.php'); + if ( !i18n::init('UTF-8', '../nucleus/locales') ) + { + exit('
Failed to initialize iconv or mbstring extension. Would you please contact the administrator of your PHP server?
'); + } + + // include core classes that are needed for login & plugin handling + + // added for 3.5 sql_* wrapper + global $MYSQL_HANDLER; + + if ( !isset($MYSQL_HANDLER) ) + { + $MYSQL_HANDLER = array('mysql', ''); + + // check if mysql support is installed; this check may not make sense, as is, in a version past 3.5x + if ( !function_exists('mysql_query') && !function_exists('mysqli_query') ) + { + exit('
Your PHP version does not have support for MySQL :(
'); + } + } + include_once('../nucleus/libs/sql/sql.php'); + + session_start(); + if ( count($_GET) == 0 && count($_POST) == 0 ) + { + unset($_SESSION['param_manager']); + } + + // restore the $param from the session + if ( array_key_exists('param_manager', $_SESSION) ) + { + $param = $_SESSION['param_manager']; + } + else + { + $param = new ParamManager(); + } + + // include translation file + $param->set_locale(); + + do_action(); + + // $param is saved to the session + if ( isset($param) ) + { + $_SESSION['param_manager'] = $param; + } + else + { + unset($_SESSION['param_manager']); + } + exit; + + /** + * installer action + */ + function do_action() + { + global $param; + + if ( array_key_exists('action', $_POST) ) + { + $isPostback = true; + } + else + { + $isPostback = false; + } + + // mode change + if ( array_key_exists('mode', $_REQUEST) ) + { + if ( $_REQUEST['mode'] == 'detail' ) + { + $param->set_state('detail'); + } + elseif ( $_REQUEST['mode'] == 'simple' ) + { + $param->set_state('mysql'); + } + } + + // input parameter check + if ( $isPostback ) + { + switch ( $param->state ) + { + case 'locale': + $param->set_state('mysql'); + $isPostback = false; + break; + case 'mysql': + if ( count($param->check_mysql_parameters()) == 0 ) + { + $param->set_state('weblog'); + $isPostback = false; + } + break; + case 'weblog': + if ( count($param->check_user_parameters()) == 0 + && count($param->check_weblog_parameters()) == 0 ) + { + $param->set_state('install'); + $isPostback = false; + } + break; + case 'detail': + if ( $param->check_all_parameters() ) + { + $param->set_state('install'); + $isPostback = false; + } + break; + } + } + + // page render + show_header(); + switch ( $param->state ) + { + case 'locale': + show_select_locale_form(); + break; + case 'mysql': + show_database_setting_form($isPostback); + break; + case 'weblog': + show_blog_setting_form($isPostback); + break; + case 'detail': + show_detail_setting_form($isPostback); + break; + case 'install': + show_install_complete_form(); + break; + } + show_footer(); + } + + /** + * header tag of the installation screens + **/ + function show_header() + { + global $param; + + /* HTTP 1.1 application for no caching */ + header("Cache-Control: no-cache, must-revalidate"); + header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); + header('Content-Type: text/html; charset=' . i18n::get_current_charset()); + ?> + + + + <?php echo _TITLE; ?> + + + + + + + + + + + +
+

+ +

+
+ +
+ +

+

+

+

+ +

+
+
+
+ +
+

+ ', $config_writable, ''; + } + if ( $mysql_version == '0.0.0' ) + { + echo '', _DBVERSION_UNKOWN, ''; + } + elseif ( version_compare($mysql_version, $minimum_mysql_version, '<') ) + { + echo '', sprintf(_DBVERSION_TOOLOW, $minimum_mysql_version), ''; + } + ?> +

+
+
+

+

+ check_mysql_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } + ?> +

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

+ + +

+

+ +

+
+
+
+ +
+

+ +

+
+
+

+

+ check_weblog_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } + ?> +

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

+

+ check_user_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } + ?> +

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

+ +

+
+
+
+ +
+

+ + check_all_parameters() ) + { + echo '', _VALID_ERROR, "\n"; + } + ?> +

+ +
+ +
+

+

+ check_mysql_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } + ?> +

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

+

+ check_uri_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + $errors = $param->check_path_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } + ?> +

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

+ +

+ +

+

+ check_user_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } + ?> +

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

+

+ check_weblog_parameters(); + if ( is_array($errors) ) + { + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + } + ?> +

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

+ +

+ +

+ +

+
+
+
+ +
+

+ 0 ) + { + echo _INST_ERROR; + foreach ( $errors as $error ) + { + echo '', $error, "\n"; + } + } + else + { + echo _INST_TEXT; + if ( array_key_exists('config_data', $_SESSION) ) + { + echo '', _INST_TEXT4, ''; + ?> + + ', _INST_TEXT5, ''; + } + ?> +

+
+
+

+

+ blog_name); ?> +

+

+ +

+
+ +
+

+

+ +

+

+ +

+
+ +
+

+

+ +

+

+ +

+
+
+ +
+ mysql_host; + $MYSQL_USER = $param->mysql_user; + $MYSQL_PASSWORD = $param->mysql_password; + $MYSQL_DATABASE = $param->mysql_database; + $MYSQL_PREFIX = $param->mysql_tablePrefix; + + $DIR_NUCLEUS = $param->AdminPath; + $DIR_MEDIA = $param->MediaPath; + $DIR_SKINS = $param->SkinsPath; + $DIR_PLUGINS = $DIR_NUCLEUS . 'plugins/'; + $DIR_LOCALES = $DIR_NUCLEUS . 'locales/'; + $DIR_LIBS = $DIR_NUCLEUS . 'libs/'; + + /* + * 2.open mySQL connection + */ + $MYSQL_CONN = @DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD); + if ( $MYSQL_CONN == FALSE ) + { + $errors[] = _DBCONNECT_ERROR; + return $errors; + } + + /* + * 3. try to create database if needed + */ + if ( DB::execute("CREATE DATABASE IF NOT EXISTS {$MYSQL_DATABASE}") === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR1 . ': ' . $errinfo[2]; + } + + /* + * 4. try to select database + */ + $MYSQL_CONN = @DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE); + if ( !$MYSQL_CONN ) + { + $errors[] = _INST_ERROR2; + } + + if ( count($errors) > 0 ) + { + return $errors; + } + + /* + * 5. execute queries + */ + $table_names = array( + 'nucleus_actionlog', + 'nucleus_ban', + 'nucleus_blog', + 'nucleus_category', + 'nucleus_comment', + 'nucleus_config', + 'nucleus_item', + 'nucleus_karma', + 'nucleus_member', + 'nucleus_plugin', + 'nucleus_skin', + 'nucleus_template', + 'nucleus_team', + 'nucleus_activation', + 'nucleus_tickets' + ); + + $prefixed_table_names = array(); + foreach ( $table_names as $table_name ) + { + $prefixed_table_names[] = $MYSQL_PREFIX . $table_name; + } + + // table exists check + $result = DB::getResult('SHOW TABLES'); + foreach ( $result as $row ) + { + if ( in_array($row[0], $prefixed_table_names) ) + { + $errors[] = _INST_ERROR3; + break; + } + } + if ( count($errors) > 0 ) + { + return $errors; + } + + $filename = 'install.sql'; + $fd = fopen($filename, 'r'); + $queries = fread($fd, filesize($filename)); + fclose($fd); + + $queries = preg_split('#(;\n|;\r)#', $queries); + + foreach ( $queries as $query ) + { + if ( preg_match('/\w+/', $query) ) + { + if ( $MYSQL_PREFIX ) + { + $query = str_replace($table_names, $prefixed_table_names, $query); + } + + if ( DB::execute($query) === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR4 . ' (' . $query . '): ' . $errinfo[2]; + } + } + } + + /* + * 6. put needed records + */ + /* push first post */ + $query = "INSERT INTO %s VALUES (1, %s, %s, %s, 1, 1, %s, 0, 0, 0, 1, 0, 1)"; + $query = sprintf($query, + tableName('nucleus_item'), + DB::quoteValue(_1ST_POST_TITLE), + DB::quoteValue(_1ST_POST), + DB::quoteValue(_1ST_POST2), + DB::formatDateTime() + ); + if ( DB::execute($query) === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR4 . ' (' . $query . '): ' . $errinfo[2]; + } + + /* push configurations */ + array_merge($errors, updateConfig('IndexURL', $param->IndexURL)); + array_merge($errors, updateConfig('AdminURL', $param->AdminURL)); + array_merge($errors, updateConfig('MediaURL', $param->MediaURL)); + array_merge($errors, updateConfig('SkinsURL', $param->SkinsURL)); + array_merge($errors, updateConfig('PluginURL', $param->PluginURL)); + array_merge($errors, updateConfig('ActionURL', $param->ActionURL)); + array_merge($errors, updateConfig('AdminEmail', $param->user_email)); + array_merge($errors, updateConfig('SiteName', $param->blog_name)); + array_merge($errors, updateConfig('Locale', i18n::get_current_locale())); + + /* push super admin */ + $query = "UPDATE %s SET mname = %s, mrealname = %s, mpassword = %s, memail = %s, murl = %s, madmin = 1, mcanlogin = 1 WHERE mnumber = 1"; + $query = sprintf($query, + tableName('nucleus_member'), + DB::quoteValue($param->user_name), + DB::quoteValue($param->user_realname), + DB::quoteValue(md5($param->user_password)), + DB::quoteValue($param->user_email), + DB::quoteValue($param->IndexURL) + ); + if ( DB::execute($query) === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR5 . ': ' . $errinfo[2]; + } + + /* push new weblog */ + $query = "UPDATE %s SET bname = %s, bshortname = %s, burl = %s WHERE bnumber = 1"; + $query = sprintf($query, + tableName('nucleus_blog'), + DB::quoteValue($param->blog_name), + DB::quoteValue($param->blog_shortname), + DB::quoteValue($param->IndexURL) + ); + if ( DB::execute($query) === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR6 . ': ' . $errinfo[2]; + } + + /* push default category */ + $query = "UPDATE %s SET cname = %s, cdesc = %s WHERE catid = 1"; + $query = sprintf($query, + tableName('nucleus_category'), + DB::quoteValue(_GENERALCAT_NAME), + DB::quoteValue(_GENERALCAT_DESC) + ); + if ( DB::execute($query) === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR6 . ': ' . $errinfo[2]; + } + + /* + * 7. install default plugins and skins + */ + global $aConfPlugsToInstall, $aConfSkinsToImport; + $aSkinErrors = array(); + $aPlugErrors = array(); + + if ( (count($aConfPlugsToInstall) > 0) || (count($aConfSkinsToImport) > 0) ) + { + include_once($DIR_LIBS . 'globalfunctions.php'); + global $manager; + if ( !isset($manager) ) + { + $manager = new Manager(); + } + + include_once($DIR_LIBS . 'skinie.php'); + + $aSkinErrors = installCustomSkins(); + if ( count($aSkinErrors) > 0 ) + { + array_merge($errors, $aSkinErrors); + } + + $query = "SELECT sdnumber FROM %s WHERE sdname='admin/default'"; + $query = sprintf($query, tableName('nucleus_skin_desc')); + $res = intval(DB::getValue($query)); + array_merge($errors, updateConfig('AdminSkin', $res)); + + $query = "SELECT sdnumber FROM %s WHERE sdname='admin/bookmarklet'"; + $query = sprintf($query, tableName('nucleus_skin_desc')); + $res = intval(DB::getValue($query)); + array_merge($errors, updateConfig('BookmarkletSkin', $res)); + + $query = "SELECT sdnumber FROM %s WHERE sdname='default'"; + $query = sprintf($query, tableName('nucleus_skin_desc')); + $defSkinID = intval(DB::getValue($query)); + + $query = "UPDATE %s SET bdefskin=%d WHERE bnumber=1"; + $query = sprintf($query, tableName('nucleus_blog'), $defSkinID); + DB::execute($query); + $query = "UPDATE %s SET value=%d WHERE name='BaseSkin'"; + $query = sprintf($query, tableName('nucleus_config'), $defSkinID); + DB::execute($query); + + $aPlugErrors = installCustomPlugs(); + if ( count($aPlugErrors) > 0 ) + { + array_merge($errors, $aPlugErrors); + } + } + + /* + * 8. Write config file ourselves (if possible) + */ + $config_data = '<' . '?php' . "\n"; + $config_data .= "// mySQL connection information\n"; + $config_data .= "\$MYSQL_HOST = '" . $MYSQL_HOST . "';\n"; + $config_data .= "\$MYSQL_USER = '" . $MYSQL_USER . "';\n"; + $config_data .= "\$MYSQL_PASSWORD = '" . $MYSQL_PASSWORD . "';\n"; + $config_data .= "\$MYSQL_DATABASE = '" . $MYSQL_DATABASE . "';\n"; + $config_data .= "\$MYSQL_PREFIX = '" . $MYSQL_PREFIX . "';\n"; + $config_data .= "// new in 3.50. first element is db handler, the second is the db driver used by the handler\n"; + $config_data .= "// default is \$MYSQL_HANDLER = array('mysql','mysql');\n"; + $config_data .= "//\$MYSQL_HANDLER = array('mysql','mysql');\n"; + $config_data .= "//\$MYSQL_HANDLER = array('pdo','mysql');\n"; + $config_data .= "\$MYSQL_HANDLER = array('" . $MYSQL_HANDLER[0] . "','" . $MYSQL_HANDLER[1] . "');\n"; + $config_data .= "\n"; + $config_data .= "// main nucleus directory\n"; + $config_data .= "\$DIR_NUCLEUS = '" . $DIR_NUCLEUS . "';\n"; + $config_data .= "\n"; + $config_data .= "// path to media dir\n"; + $config_data .= "\$DIR_MEDIA = '" . $DIR_MEDIA . "';\n"; + $config_data .= "\n"; + $config_data .= "// extra skin files for imported skins\n"; + $config_data .= "\$DIR_SKINS = '" . $DIR_SKINS . "';\n"; + $config_data .= "\n"; + $config_data .= "// these dirs are normally sub dirs of the nucleus dir, but \n"; + $config_data .= "// you can redefine them if you wish\n"; + $config_data .= "\$DIR_PLUGINS = \$DIR_NUCLEUS . 'plugins/';\n"; + $config_data .= "\$DIR_LOCALES = \$DIR_NUCLEUS . 'locales/';\n"; + $config_data .= "\$DIR_LIBS = \$DIR_NUCLEUS . 'libs/';\n"; + $config_data .= "\n"; + $config_data .= "// include libs\n"; + $config_data .= "include(\$DIR_LIBS.'globalfunctions.php');\n"; + $config_data .= "?" . ">"; + + $result = false; + if ( @!file_exists('../config.php') || is_writable('../config.php') ) + { + if ( $fp = @fopen('../config.php', 'w') ) + { + $result = @fwrite($fp, $config_data, i18n::strlen($config_data)); + fclose($fp); + } + } + + if ( $result ) + { + // try to change the read-only permission. + if ( strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' ) + { + @chmod('../config.php', 0444); + } + } + else + { + $_SESSION['config_data'] = $config_data; + } + + return $errors; + } + + /** + * Confirm that you can write to the configuration file + * @return string error message + */ + function canConfigFileWritable() + { + if ( @file_exists('../config.php') && @!is_writable('../config.php') ) + { + // try to change the read-write permission. + if ( strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' ) + { + @chmod('../config.php', 0666); + } + + if ( @!is_writable('../config.php') ) + { + return _INST_ERROR8; + } + } + return ''; + } + + /** + * To obtain the version of MySQL + * @return string + */ + function getMySqlVersion() + { + global $MYSQL_HANDLER, $minimum_mysql_version, $errors; + // Turn on output buffer + // Needed to repress the output of the sql function that are + // not part of php (in this case the @ operator doesn't work) + ob_start(); + + // note: this piece of code is taken from phpMyAdmin + $conn = @DB::setConnectionInfo($MYSQL_HANDLER[1], 'localhost', '', ''); + + if ( $conn ) + { + $row = DB::getAttribute(PDO::ATTR_SERVER_VERSION); + $match = preg_split('#\.#', $row); + } + else + { + $row = @DB::getRow('SHOW VARIABLES LIKE \'version\''); + + if ( $row ) + { + $match = preg_split('#\.#', $row[1]); + } + else + { + $output = (function_exists('shell_exec')) ? @shell_exec('mysql -V') : '0.0.0'; + preg_match('@[0-9]+\.[0-9]+\.[0-9]+@', $output, $version); + $match = preg_split('#\.#', $version[0]); + + if ( $match[0] == '' ) + { + $match = array('0', '0', '0'); + } + } + } + + @DB::disConnect(); + + //End and clean output buffer + ob_end_clean(); + + return implode($match, '.'); + } + + /** + * Add a table prefix if it is used + * + * @param string $input table name with prefix + * @return string + */ + function tableName($input) + { + global $MYSQL_PREFIX; + if ( $MYSQL_PREFIX ) + { + return $MYSQL_PREFIX . $input; + } + else + { + return $input; + } + } + + /** + * Install custom plugins + */ + function installCustomPlugs() + { + global $aConfPlugsToInstall, $DIR_LIBS, $manager; + + $aErrors = array(); + if ( count($aConfPlugsToInstall) == 0 ) + { + return $aErrors; + } + + $query = sprintf('SELECT * FROM %s', tableName('nucleus_plugin')); + $res = DB::getResult($query); + $numCurrent = $res->rowCount(); + + foreach ( $aConfPlugsToInstall as $plugName ) + { + $query = sprintf('INSERT INTO %s (porder, pfile) VALUES (%d, %s)', + tableName('nucleus_plugin'), + (++$numCurrent), + DB::quoteValue($plugName)); + DB::execute($query); + + $manager->clearCachedInfo('installedPlugins'); + $plugin =& $manager->getPlugin($plugName); + $plugin->setID($numCurrent); + + if ( !$plugin ) + { + $query = sprintf('DELETE FROM %s WHERE pfile = %s', + tableName('nucleus_plugin'), + DB::quoteValue($plugName)); + DB::execute($query); + $numCurrent--; + array_push($aErrors, sprintf(_INST_ERROR9, $plugName)); + continue; + } + $plugin->install(); + } + + $query = sprintf('DELETE FROM %s', tableName('nucleus_plugin_event')); + DB::execute($query); + $query = sprintf('SELECT pid, pfile FROM %s', tableName('nucleus_plugin')); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $plug =& $manager->getPlugin($row['pfile']); + + if ( $plug ) + { + $eventList = $plug->getEventList(); + foreach ( $eventList as $eventName ) + { + $query = sprintf('INSERT INTO %s (pid, event) VALUES (%d, %s)', + tableName('nucleus_plugin_event'), + intval($row['pid']), + DB::quoteValue($eventName)); + DB::execute($query); + } + } + } + return $aErrors; + } + + /** + * Install custom skins + * Prepares the installation of custom skins + */ + function installCustomSkins() + { + global $aConfSkinsToImport, $DIR_LIBS, $DIR_SKINS; + + $aErrors = array(); + if ( count($aConfSkinsToImport) == 0 ) + { + return $aErrors; + } + + $importer = new SkinImport(); + + foreach ( $aConfSkinsToImport as $skinName ) + { + $importer->reset(); + $skinFile = $DIR_SKINS . $skinName . '/skinbackup.xml'; + + if ( !@file_exists($skinFile) ) + { + array_push($aErrors, sprintf(_INST_ERROR10, $skinFile)); + continue; + } + + $error = $importer->readFile($skinFile); + + if ( $error ) + { + array_push($aErrors, sprintf(_INST_ERROR11, $skinName) . ' : ' . $error); + continue; + } + + $error = $importer->writeToDatabase(1); + + if ( $error ) + { + array_push($aErrors, sprintf(_INST_ERROR12, $skinName) . ' : ' . $error); + continue; + } + } + return $aErrors; + } + + /** + * Check if some important files of the Nucleus CMS installation are available + * Give an error if one or more files are not accessible + */ + function do_check_files() + { + $missingfiles = array(); + $files = array( + './install.sql', + '../index.php', + '../action.php', + '../nucleus/index.php', + '../nucleus/libs/ACTION.php', + '../nucleus/libs/ACTIONLOG.php', + '../nucleus/libs/ACTIONS.php', + '../nucleus/libs/ADMIN.php', + '../nucleus/libs/BaseActions.php', + '../nucleus/libs/BLOG.php', + '../nucleus/libs/BODYACTIONS.php', + '../nucleus/libs/COMMENT.php', + '../nucleus/libs/COMMENTACTIONS.php', + '../nucleus/libs/COMMENTS.php', + '../nucleus/libs/ENTITY.php', + '../nucleus/libs/globalfunctions.php', + '../nucleus/libs/i18n.php', + '../nucleus/libs/ITEM.php', + '../nucleus/libs/ITEMACTIONS.php', + '../nucleus/libs/LINK.php', + '../nucleus/libs/MANAGER.php', + '../nucleus/libs/MEDIA.php', + '../nucleus/libs/MEMBER.php', + '../nucleus/libs/NOTIFICATION.php', + '../nucleus/libs/PARSER.php', + '../nucleus/libs/PLUGIN.php', + '../nucleus/libs/PLUGINADMIN.php', + '../nucleus/libs/SEARCH.php', + '../nucleus/libs/showlist.php', + '../nucleus/libs/SKIN.php', + '../nucleus/libs/TEMPLATE.php', + '../nucleus/libs/vars4.1.0.php', + '../nucleus/libs/xmlrpc.inc.php', + '../nucleus/libs/xmlrpcs.inc.php', + '../nucleus/libs/sql/DB.php', + '../nucleus/libs/sql/MYSQLPDO.php' + ); + + $count = count($files); + for ( $i = 0; $i < $count; $i++ ) + { + if ( !is_readable($files[$i]) ) + { + array_push($missingfiles, 'File ' . $files[$i] . ' is missing or not readable.
'); + } + } + + if ( count($missingfiles) > 0 ) + { + exit(implode("\n", $missingfiles)); + } + } + + /** + * Updates the configuration in the database + * + * @param string $name name of the config var + * @param string $value new value of the config var + * @return array + */ + function updateConfig($name, $value) + { + $errors = array(); + + $query = "UPDATE %s SET value = %s WHERE name = %s"; + $query = sprintf($query, tableName('nucleus_config'), DB::quoteValue(trim($value)), DB::quoteValue($name)); + + if ( DB::execute($query) === FALSE ) + { + $errinfo = DB::getError(); + $errors[] = _INST_ERROR4 . ': ' . $errinfo[2]; + } + return $errors; + } + + class ParamManager + { + /* process parameter */ + public $state; + public $locale; + + /* mysql connection parameters */ + public $mysql_host; + public $mysql_user; + public $mysql_password; + public $mysql_database; + public $mysql_tablePrefix; + + /* weblog configuration parameters */ + public $blog_name; + public $blog_shortname; + + /* member configuration parameters */ + public $user_name; + public $user_realname; + public $user_password; + private $user_password2; + public $user_email; + + /* URI parameters */ + private $root_url; + public $IndexURL; + public $AdminURL; + public $MediaURL; + public $SkinsURL; + public $PluginURL; + public $ActionURL; + + /* path parameters */ + private $root_path; + public $AdminPath; + public $MediaPath; + public $SkinsPath; + + /** + * constructor + */ + public function __construct() + { + $this->init(); + } + + public function init() + { + // set default values + $this->state = 'locale'; + $this->install_mode = 'simple'; + $this->locale = ''; + $this->mysql_host = @ini_get('mysql.default_host'); + $this->blog_name = 'My Nucleus CMS'; + $this->blog_shortname = 'mynucleuscms'; + + /* root path */ + $directory_separator = preg_quote(DIRECTORY_SEPARATOR, '|'); + $this->root_path = implode('/', preg_split("|$directory_separator|", realpath(dirname(__FILE__) . '/..'))); + if ( substr($this->root_path, -1, 1) !== '/' ) + { + $this->root_path .= '/'; + } + $base_path_pcre = preg_quote($this->root_path, '|'); + + /* current directry name */ + $directory_name = preg_replace("#{$base_path_pcre}#", '', implode('/', preg_split("#{$directory_separator}#", realpath(dirname(__FILE__))))); + $directory_name_pcre = preg_quote($directory_name, '|'); + + /* root uri */ + $root_url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']; + $this->root_url = preg_replace("|$directory_name_pcre(.*)$|", '', $root_url); + + $this->AdminPath = $this->root_path . 'nucleus/'; + $this->MediaPath = $this->root_path . 'media/'; + $this->SkinsPath = $this->root_path . 'skins/'; + + $this->IndexURL = $this->root_url; + $this->AdminURL = $this->root_url . 'nucleus/'; + $this->MediaURL = $this->root_url . 'media/'; + $this->SkinsURL = $this->root_url . 'skins/'; + $this->PluginURL = $this->root_url . 'nucleus/plugins/'; + $this->ActionURL = $this->root_url . 'action.php'; + } + + private function read_parameter($parameter) + { + foreach ( $parameter as $element ) + { + if ( array_key_exists($element, $_POST) ) + { + $this->$element = $_POST[$element]; + } + } + } + + public function set_state($state) + { + $states = array('locale', 'mysql', 'weblog', 'detail', 'install'); + if ( in_array($state, $states) ) + { + $this->state = $state; + } + } + + public function set_locale() + { + $this->read_parameter(array('locale')); + + if ( !$this->locale ) + { + /** + * default locale select simple implementation + * + * NOTE: + * RFC2616: Hypertext Transfer Protocol -- HTTP/1.1 + * http://www.ietf.org/rfc/rfc2616.txt + * + * 14.4 Accept-Language + * + * The Accept-Language request-header field is similar to Accept, but + * restricts the set of natural languages that are preferred as a + * response to the request. Language tags are defined in section 3.10. + * + * Accept-Language = "Accept-Language" ":" + * 1#( language-range [ ";" "q" "=" qvalue ] ) + * language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) + * + * Each language-range MAY be given an associated quality value which + * represents an estimate of the user's preference for the languages + * specified by that range. The quality value defaults to "q=1". For + * example, + * + * Accept-Language: da, en-gb;q=0.8, en;q=0.7 + * + * would mean: "I prefer Danish, but will accept British English and + * other types of English." A language-range matches a language-tag if + * it exactly equals the tag, or if it exactly equals a prefix of the + * tag such that the first tag character following the prefix is "-". + * The special range "*", if present in the Accept-Language field, + * matches every tag not matched by any other range present in the + * Accept-Language field. + * + * TODO: this is appropriate implement or not + */ + $languages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); + + /* retrieve language token of language tag from first token */ + $language = ''; + if ( is_array($languages) && count($languages) > 0 ) + { + $language = preg_replace('#^([\w]+).*$#', '$1', $languages[0]); + } + + $locales = i18n::get_available_locale_list(); + foreach ( $locales as $locale ) + { + if ( i18n::strpos($locale, $language) === 0 ) + { + $this->locale = $locale; + break; + } + } + } + + /* include installer translation messages */ + $translation_file = "./locales/{$this->locale}." . i18n::get_current_charset() . '.php'; + if ( !file_exists($translation_file) ) + { + $translation_file = './locales/en_Latn_US.UTF-8.php'; + } + include($translation_file); + + /* include global translation messages */ + $translation_file = "../nucleus/locales/{$this->locale}." . i18n::get_current_charset() . '.php'; + if ( !file_exists($translation_file) ) + { + $translation_file = './locales/en_Latn_US.UTF-8.php'; + } + include($translation_file); + + i18n::set_current_locale($this->locale); + + return; + } + + public function check_mysql_parameters() + { + global $MYSQL_HANDLER; + + $parameters = array('mysql_host', 'mysql_user', 'mysql_password', 'mysql_database', 'mysql_tablePrefix'); + $this->read_parameter($parameters); + + $errors = array(); + if ( $this->mysql_host == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _DB_FIELD1); + } + + if ( $this->mysql_user == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _DB_FIELD2); + } + + if ( $this->mysql_user != '' + && !preg_match('/^[a-z0-9_\-]+$/i', $this->mysql_user) ) + { + $errors[] = sprintf(_VALID_ERROR2, _DB_FIELD2); + } + + if ( $this->mysql_database == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _DB_FIELD4); + } + + if ( $this->mysql_database != '' + && !preg_match('/^[a-z0-9_\-]+$/i', $this->mysql_database) ) + { + $errors[] = sprintf(_VALID_ERROR2, _DB_FIELD4); + } + + if ( $this->mysql_tablePrefix != '' + && !preg_match('/^[a-z0-9_]+$/i', $this->mysql_tablePrefix) ) + { + $errors[] = sprintf(_VALID_ERROR3, _DB_FIELD5); + } + + if ( count($errors) == 0 ) + { + $mysql_conn = @DB::setConnectionInfo($MYSQL_HANDLER[1], $this->mysql_host, $this->mysql_user, $this->mysql_password); + if ( $mysql_conn == false ) + { + $errors[] = _DBCONNECT_ERROR; + } + else + { + @DB::disConnect(); + } + } + + return $errors; + } + + public function check_user_parameters() + { + $parameters = array('user_name', 'user_realname', 'user_password', 'user_password2', 'user_email'); + $this->read_parameter($parameters); + + $errors = array(); + if ( $this->user_realname == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _ADMIN_FIELD1); + } + + if ( $this->user_name == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _ADMIN_FIELD2); + } + elseif ( !preg_match("/^[a-z0-9]+([ a-z0-9]*[a-z0-9]+)?$/i", $this->user_name) ) + { + $errors[] = _VALID_ERROR5; + } + + if ( $this->user_password == '' || $this->user_password2 == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _ADMIN_FIELD3); + $this->user_password = ''; + } + elseif ( $this->user_password != $this->user_password2 ) + { + $errors[] = _VALID_ERROR6; + $this->user_password = ''; + } + + if ( !preg_match("/^[a-z0-9\._+\-]+@[a-z0-9\._\-]+\.[a-z]{2,6}$/i", $this->user_email) ) + { + $errors[] = _VALID_ERROR7; + } + + return $errors; + } + + public function check_weblog_parameters() + { + $parameters = array('blog_name', 'blog_shortname'); + $this->read_parameter($parameters); + + $errors = array(); + if ( $this->blog_name == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _BLOG_FIELD1); + } + + if ( $this->blog_shortname == '' ) + { + $errors[] = sprintf(_VALID_ERROR1, _BLOG_FIELD2); + } + + if ( !preg_match("/^[a-z0-9]+$/i", $this->blog_shortname) ) + { + $errors[] = _VALID_ERROR4; + } + + return $errors; + } + + public function check_uri_parameters() + { + $parameters = array('IndexURL', 'AdminURL', 'MediaURL', 'SkinsURL', 'PluginURL', 'ActionURL'); + $this->read_parameter($parameters); + + $errors = array(); + if ( substr($this->IndexURL, -1, 1) !== '/' ) + { + $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD1); + } + + if ( substr($this->AdminURL, -1, 1) !== '/' ) + { + $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD2); + } + + if ( substr($this->MediaURL, -1, 1) !== '/' ) + { + $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD4); + } + + if ( substr($this->SkinsURL, -1, 1) !== '/' ) + { + $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD6); + } + + if ( substr($this->PluginURL, -1, 1) !== '/' ) + { + $errors[] = sprintf(_VALID_ERROR8, _PATH_FIELD8); + } + + if ( strrchr($this->ActionURL, '/') != '/action.php' ) + { + $errors[] = sprintf(_VALID_ERROR9, _PATH_FIELD9); + } + + return $errors; + } + + public function check_path_parameters() + { + $parameters = array('AdminPath', 'MediaPath', 'SkinsPath'); + $this->read_parameter($parameters); + + $separators = array('/', DIRECTORY_SEPARATOR); + $errors = array(); + if ( !in_array(substr($this->AdminPath, -1, 1), $separators) ) + { + $errors[] = sprintf(_VALID_ERROR10, _PATH_FIELD3); + } + elseif ( !file_exists($this->AdminPath) ) + { + $errors[] = sprintf(_VALID_ERROR11, _PATH_FIELD3); + } + + if ( !in_array(substr($this->MediaPath, -1, 1), $separators) ) + { + $errors[] = sprintf(_VALID_ERROR10, _PATH_FIELD5); + } + elseif ( !file_exists($this->MediaPath) ) + { + $errors[] = sprintf(_VALID_ERROR11, _PATH_FIELD5); + } + + if ( !in_array(substr($this->SkinsPath, -1, 1), $separators) ) + { + $errors[] = sprintf(_VALID_ERROR10, _PATH_FIELD7); + } + elseif ( !file_exists($this->SkinsPath) ) + { + $errors[] = sprintf(_VALID_ERROR11, _PATH_FIELD7); + } + + return $errors; + } + + /** + * check all parameters + * @return bool + */ + public function check_all_parameters() + { + $this->set_locale(); + + $isValid = true; + $isValid &= (count($this->check_mysql_parameters()) == 0); + $isValid &= (count($this->check_user_parameters()) == 0); + $isValid &= (count($this->check_weblog_parameters()) == 0); + $isValid &= (count($this->check_uri_parameters()) == 0); + $isValid &= (count($this->check_path_parameters()) == 0); + + return $isValid; + } + } ++>>>>>>> skinnable-master diff --combined nucleus/bookmarklet.php index 6278c97,61af96c..836b920 --- a/nucleus/bookmarklet.php +++ b/nucleus/bookmarklet.php @@@ -25,11 -25,25 +25,32 @@@ $CONF['UsingAdminArea'] = 1 // include all classes and config data include('../config.php'); ++<<<<<<< HEAD ++======= + // get skin object + $skinid = $member->bookmarklet; + if ( !Skin::existsID($skinid) ) + { + $skinid = $CONF['BookmarkletSkin']; + if ( !Skin::existsID($skinid) ) + { + sendContentType('text/html'); + echo _ERROR_SKIN; + exit; + } + } + $skin =& $manager->getSkin($skinid, 'AdminActions', 'AdminSkin'); + ++>>>>>>> skinnable-master // check logged-in or pass through $action = requestVar('action'); if ( !$member->isLoggedIn() ) { ++<<<<<<< HEAD + bm_loginAndPassThrough($action); ++======= + bm_loginAndPassThrough($skin, $action); ++>>>>>>> skinnable-master exit; } else if ( $action == 'login') @@@ -49,16 -63,13 +70,19 @@@ else if ( $action == '' $action = 'add'; } ++<<<<<<< HEAD +// send HTTP 1.1 message header for Content-Type +sendContentType('text/html', 'bookmarklet-' . $action); + ++======= ++>>>>>>> skinnable-master // check ticket $aActionsNotToCheck = array('login', 'add', 'edit'); if ( !in_array($action, $aActionsNotToCheck) ) { if ( !$manager->checkTicket() ) { - bm_doError(_ERROR_BADTICKET); + bm_doError($skin, _ERROR_BADTICKET); } } @@@ -67,32 -78,32 +91,32 @@@ switch ( $action { // adds the item for real case 'additem': - bm_doAddItem(); + bm_doAddItem($skin); break; // shows the edit item form case 'edit': - bm_doEditForm(); + bm_doEditForm($skin); break; // edits the item for real case 'edititem': - bm_doEditItem(); + bm_doEditItem($skin); break; // on login, 'action' gets changed to 'nextaction' case 'login': - bm_doError('Something went wrong'); + bm_doError($skin, 'Something went wrong'); break; // shows the fill in form case 'add': default: - bm_doShowForm(); + bm_doShowForm($skin); break; } - function bm_doAddItem() + function bm_doAddItem($skin) { global $member, $manager, $CONF; @@@ -101,7 -112,7 +125,7 @@@ if ( $result['status'] == 'error' ) { - bm_doError($result['message']); + bm_doError($skin, $result['message']); } $blogid = getBlogIDFromItemID($result['itemid']); @@@ -118,12 -129,12 +142,16 @@@ $extrahead = ''; } ++<<<<<<< HEAD + bm_message(_ITEM_ADDED, _ITEM_ADDED, $message,$extrahead); ++======= + bm_message($skin, _ITEM_ADDED, $message,$extrahead); ++>>>>>>> skinnable-master return; } - function bm_doEditItem() + function bm_doEditItem($skin) { global $member, $manager, $CONF; @@@ -133,7 -144,7 +161,7 @@@ // only allow if user is allowed to alter item if ( !$member->canUpdateItem($itemid, $catid) ) { - bm_doError(_ERROR_DISALLOWED); + bm_doError($skin, _ERROR_DISALLOWED); } $body = postVar('body'); @@@ -163,7 -174,7 +191,7 @@@ // show error when sth goes wrong if ( !$catid ) { - bm_doError('Could not create new category'); + bm_doError($skin, 'Could not create new category'); } } @@@ -186,7 -197,7 +214,7 @@@ $timestamp = 0; break; default: - bm_doError('Something went wrong'); + bm_doError($skin, 'Something went wrong'); } // update item for real @@@ -197,58 -208,48 +225,81 @@@ Item::delete($draftid); } - // show success message - if ( $catid != intPostVar('catid') ) + if ( $result['status'] == 'newcategory' ) { - bm_message(_ITEM_UPDATED, _ITEM_UPDATED, 'Item was added, and a new category was created. Click here to edit the name and description of the category.', ''); + $href = "index.php?action=categoryedit&blogid={$blogid}&catid={$result['catid']}"; + $onclick = 'if (event && event.preventDefault) event.preventDefault(); window.open(this.href); return false;'; + $title = _BOOKMARKLET_NEW_WINDOW; + $aTag = " "; + $message = _BOOKMARKLET_NEW_CATEGORY . $aTag . _BOOKMARKLET_NEW_CATEGORY_EDIT . ''; } else { - bm_message(_ITEM_UPDATED, _ITEM_UPDATED, _ITEM_UPDATED, ''); + $message = _ITEM_ADDED; } ++<<<<<<< HEAD + return; +} + +function bm_loginAndPassThrough($action='add') ++======= + // show success message + bm_message($skin, _ITEM_ADDED, $message, ''); + return; + } + + function bm_loginAndPassThrough($skin, $action='add') ++>>>>>>> skinnable-master { + /* + * TODO: これを出力させる $blogid = intRequestVar('blogid'); $itemid = intRequestVar('itemid'); $log_text = requestVar('logtext'); $log_link = requestVar('loglink'); $log_linktitle = requestVar('loglinktitle'); ++<<<<<<< HEAD + echo "\n"; + echo "\n"; + echo "\n"; + echo "Nucleus CMS Bookmarklet\n"; + + bm_style(); + + echo "\n"; + echo "\n"; + echo '

' . _LOGIN_PLEASE . "

\n"; + echo "
\n"; + echo "

\n"; + echo _LOGINFORM_NAME . "
\n"; + echo _LOGINFORM_PWD . "
\n"; ++======= ++>>>>>>> skinnable-master echo '' . "\n"; echo '' . "\n"; echo '' . "\n"; echo '' . "\n"; echo '' . "\n"; echo "\n"; ++<<<<<<< HEAD + echo '\n"; + echo "

\n"; + echo "
\n"; + echo '

' . _POPUP_CLOSE . "

\n"; + echo "\n"; + echo "\n"; ++======= + */ + + $skin->parse('showlogin'); ++>>>>>>> skinnable-master return; } - function bm_doShowForm() + function bm_doShowForm($skin) { global $manager, $member; @@@ -259,18 -260,15 +310,24 @@@ if ( !Blog::existsID($blogid) ) { - bm_doError(_ERROR_NOSUCHBLOG); + bm_doError($skin, _ERROR_NOSUCHBLOG); } ++<<<<<<< HEAD + else + { + $blog =& $manager->getBlog($blogid); + } + + if ( !$member->isTeamMember($blogid) ) ++======= + else if ( !$member->isTeamMember($blogid) ) ++>>>>>>> skinnable-master { - bm_doError(_ERROR_NOTONTEAM); + bm_doError($skin, _ERROR_NOTONTEAM); } + $blog =& $manager->getBlog($blogid); + $logje = ''; if ( $log_text ) @@@ -288,23 -286,32 +345,48 @@@ $logje .= '' . Entity::hsc($log_linktitle) . ''; } ++<<<<<<< HEAD + $variables = array(); + $variables['body'] = $logje; + $variables['title'] = Entity::hsc($log_linktitle); + + $handler = new PageFactory($blog); + $handler->setVariables($variables); + + $contents = $handler->getTemplateFor('bookmarklet', 'add'); + $manager->notify('PreAddItemForm', array('contents' => &$contents, 'blog' => &$blog)); + + $parser = new Parser($handler); + $parser->parse($contents); + ++======= + $item = array(); + $item['body'] = $logje; + $item['title'] = Entity::hsc($log_linktitle); + + $data = array( + 'blog' => &$blog, + 'item' => &$item, + 'contents' => &$item + ); + $manager->notify('PreAddItemForm', $data); + + if ( $blog->convertBreaks() ) + { + $item['body'] = removeBreaks($item['body']); + } + + Admin::$blog = &$blog; + Admin::$contents = &$item; + + Admin::$action = 'createitem'; + $skin->parse('createitem'); + ++>>>>>>> skinnable-master return; } - function bm_doEditForm() + function bm_doEditForm($skin) { global $member, $manager; @@@ -312,74 -319,54 +394,105 @@@ if ( !$manager->existsItem($itemid, 0, 0) ) { - bm_doError(_ERROR_NOSUCHITEM); + bm_doError($skin, _ERROR_NOSUCHITEM); } - - if ( !$member->canAlterItem($itemid) ) + else if ( !$member->canAlterItem($itemid) ) { - bm_doError(_ERROR_DISALLOWED); + bm_doError($skin, _ERROR_DISALLOWED); } ++<<<<<<< HEAD + $variables =& $manager->getItem($itemid, 1, 1); ++======= ++>>>>>>> skinnable-master $blog =& $manager->getBlog(getBlogIDFromItemID($itemid) ); + $item =& $manager->getItem($itemid, 1, 1); ++<<<<<<< HEAD + $manager->notify('PrepareItemForEdit', array('item' => &$variables) ); ++======= + $data = array( + 'blog' => &$blog, + 'item' => &$item + ); + $manager->notify('PrepareItemForEdit', $data); ++>>>>>>> skinnable-master if ( $blog->convertBreaks() ) { - $item['body'] = removeBreaks($item['body']); - $item['more'] = removeBreaks($item['more']); + $variables['body'] = removeBreaks($variables['body']); + $variables['more'] = removeBreaks($variables['more']); } ++<<<<<<< HEAD + $handler = new PageFactory($blog); + $handler->setVariables($variables); + + $contents = $handler->getTemplateFor('bookmarklet', 'edit'); + + $parser = new Parser($handler); + $parser->parse($contents); + + return; +} ++======= + Admin::$blog = &$blog; + Admin::$contents = &$item; + + Admin::$action = 'itemedit'; + $skin->parse('itemedit'); + + return;} ++>>>>>>> skinnable-master - function bm_doError($msg) + function bm_doError($skin, $msg) { - bm_message(_ERROR, _ERRORMSG, $msg); + bm_message($skin, _ERRORMSG, $msg); die; } - function bm_message($title, $head, $msg, $extrahead = '') + function bm_message($skin, $title, $msg, $extrahead = '') { ++<<<<<<< HEAD + echo "\n"; + echo "\n"; + echo "\n"; + echo "{$title}\n"; + + bm_style(); + + echo $extrahead . "\n"; + echo "\n"; + echo "\n"; + echo "

{$head}

\n"; + echo "

{$msg}

\n"; + echo '

' . _POPUP_CLOSE . "

\n"; + echo "\n"; + echo "\n"; ++======= + Admin::$extrahead = $extrahead; + Admin::$headMess = $msg; + $skin->parse('adminerrorpage'); ++>>>>>>> skinnable-master return; } - function bm_style() + function bm_doContextMenuCode($width=600, $height=500) { ++<<<<<<< HEAD + echo "\n"; + echo "\n"; + return; +} + +function bm_doContextMenuCode($width=600, $height=500) +{ + global $CONF; + ++======= + global $CONF; ++>>>>>>> skinnable-master $blogid = (integer) intGetVar('blogid'); echo "\n"; + + self::$skin->parse('editmembersettings'); + return; + } + + /** + * Admin::action_changemembersettings() + * + * @param void + * @return void + */ + static private function action_changemembersettings() + { + global $member, $CONF, $manager; + + $memberid = intRequestVar('memberid'); + + // check if allowed + ($member->getID() == $memberid) or $member->isAdmin() or self::disallow(); + + $name = trim(strip_tags(postVar('name'))); + $realname = trim(strip_tags(postVar('realname'))); + $password = postVar('password'); + $repeatpassword = postVar('repeatpassword'); + $email = strip_tags(postVar('email')); + $url = strip_tags(postVar('url')); + $adminskin = intPostVar('adminskin'); + $bookmarklet = intPostVar('bookmarklet'); + + // begin if: sometimes user didn't prefix the URL with http:// or https://, this cause a malformed URL. Let's fix it. + if ( !preg_match('#^https?://#', $url) ) + { + $url = 'http://' . $url; + } + + $admin = postVar('admin'); + $canlogin = postVar('canlogin'); + $notes = strip_tags(postVar('notes')); + $locale = postVar('locale'); + + $mem =& $manager->getMember($memberid); + + if ( $CONF['AllowLoginEdit'] || $member->isAdmin() ) + { + if ( !isValidDisplayName($name) ) + { + self::error(_ERROR_BADNAME); + return; + } + + if ( ($name != $mem->getDisplayName()) && Member::exists($name) ) + { + self::error(_ERROR_NICKNAMEINUSE); + return; + } + + if ( $password != $repeatpassword ) + { + self::error(_ERROR_PASSWORDMISMATCH); + return; + } + + if ( $password && (i18n::strlen($password) < 6) ) + { + self::error(_ERROR_PASSWORDTOOSHORT); + return; + } + + if ( $password ) + { + $pwdvalid = true; + $pwderror = ''; + + $data = array( + 'password' => $password, + 'errormessage' => &$pwderror, + 'valid' => &$pwdvalid + ); + $manager->notify('PrePasswordSet', $data); + + if ( !$pwdvalid ) + { + self::error($pwderror); + return; + } + } + } + + if ( !NOTIFICATION::address_validation($email) ) + { + self::error(_ERROR_BADMAILADDRESS); + return; + } + if ( !$realname ) + { + self::error(_ERROR_REALNAMEMISSING); + return; + } + if ( ($locale != '') && (!in_array($locale, i18n::get_available_locale_list())) ) + { + self::error(_ERROR_NOSUCHTRANSLATION); + return; + } + + // check if there will remain at least one site member with both the logon and admin rights + // (check occurs when taking away one of these rights from such a member) + if ( (!$admin && $mem->isAdmin() && $mem->canLogin()) + || (!$canlogin && $mem->isAdmin() && $mem->canLogin()) + ) + { + $r = DB::getResult('SELECT * FROM '.sql_table('member').' WHERE madmin=1 and mcanlogin=1'); + if ( $r->rowCount() < 2 ) + { + self::error(_ERROR_ATLEASTONEADMIN); + return; + } + } + + if ( $CONF['AllowLoginEdit'] || $member->isAdmin() ) + { + $mem->setDisplayName($name); + if ( $password ) + { + $mem->setPassword($password); + } + } + + $oldEmail = $mem->getEmail(); + + $mem->setRealName($realname); + $mem->setEmail($email); + $mem->setURL($url); + $mem->setNotes($notes); + $mem->setLocale($locale); + $mem->setAdminSkin($adminskin); + $mem->setBookmarklet($bookmarklet); + + // only allow super-admins to make changes to the admin status + if ( $member->isAdmin() ) + { + $mem->setAdmin($admin); + $mem->setCanLogin($canlogin); + } + + $autosave = postVar('autosave'); + $mem->setAutosave($autosave); + + $mem->write(); + + // store plugin options + $aOptions = requestArray('plugoption'); + NucleusPlugin::apply_plugin_options($aOptions); + $data = array( + 'context' => 'member', + 'memberid' => $memberid, + 'member' => &$mem + ); + $manager->notify('PostPluginOptionsUpdate', $data); + + // if email changed, generate new password + if ( $oldEmail != $mem->getEmail() ) + { + $mem->sendActivationLink('addresschange', $oldEmail); + // logout member + $mem->newCookieKey(); + + // only log out if the member being edited is the current member. + if ( $member->getID() == $memberid ) + { + $member->logout(); + } + self::action_login(_MSG_ACTIVATION_SENT, 0); + return; + } + + if ( ($mem->getID() == $member->getID()) + && ($mem->getDisplayName() != $member->getDisplayName()) ) + { + $mem->newCookieKey(); + $member->logout(); + self::action_login(_MSG_LOGINAGAIN, 0); + } + else + { + self::action_overview(_MSG_SETTINGSCHANGED); + } + return; + } + + /** + * Admin::action_memberadd() + * + * @param void + * @return void + * + */ + static private function action_memberadd() + { + global $member, $manager; + + // check if allowed + $member->isAdmin() or self::disallow(); + + if ( postVar('password') != postVar('repeatpassword') ) + { + self::error(_ERROR_PASSWORDMISMATCH); + return; + } + + if ( i18n::strlen(postVar('password')) < 6 ) + { + self::error(_ERROR_PASSWORDTOOSHORT); + return; + } + + $res = Member::create( + postVar('name'), + postVar('realname'), + postVar('password'), + postVar('email'), + postVar('url'), + postVar('admin'), + postVar('canlogin'), + postVar('notes') + ); + + if ( $res != 1 ) + { + self::error($res); + return; + } + + // fire PostRegister event + $newmem = new Member(); + $newmem->readFromName(postVar('name')); + $data = array( + 'member' => &$newmem + ); + $manager->notify('PostRegister', $data); + + self::action_usermanagement(); + return; + } + + /** + * Admin::action_forgotpassword() + * + * @param void + * @return void + */ + static private function action_forgotpassword() + { + self::$skin->parse('forgotpassword'); + return; + } + + /** + * Admin::action_activate() + * Account activation + * + * @param void + * @return void + */ + static private function action_activate() + { + $key = getVar('key'); + self::showActivationPage($key); + return; + } + + /** + * Admin::showActivationPage() + * + * @param void + * @return void + */ + static private function showActivationPage($key, $message = '') + { + global $manager; + + // clean up old activation keys + Member::cleanupActivationTable(); + + // get activation info + $info = Member::getActivationInfo($key); + + if ( !$info ) + { + self::error(_ERROR_ACTIVATE); + return; + } + + $mem =& $manager->getMember($info->vmember); + + if ( !$mem ) + { + self::error(_ERROR_ACTIVATE); + return; + } + + /* TODO: we should consider to use the other way insterad of this */ + $_POST['ackey'] = $key; + $_POST['bNeedsPasswordChange'] = TRUE; + + self::$headMess = $message; + self::$skin->parse('activate'); + return; + } + + /** + * Admin::action_activatesetpwd() + * Account activation - set password part + * + * @param void + * @return void + */ + static private function action_activatesetpwd() + { + global $manager; + $key = postVar('key'); + + // clean up old activation keys + Member::cleanupActivationTable(); + + // get activation info + $info = Member::getActivationInfo($key); + + if ( !$info || ($info->type == 'addresschange') ) + { + return self::showActivationPage($key, _ERROR_ACTIVATE); + } + + $mem =& $manager->getMember($info->vmember); + + if ( !$mem ) + { + return self::showActivationPage($key, _ERROR_ACTIVATE); + } + + $password = postVar('password'); + $repeatpassword = postVar('repeatpassword'); + + if ( $password != $repeatpassword ) + { + return self::showActivationPage($key, _ERROR_PASSWORDMISMATCH); + } + + if ( $password && (i18n::strlen($password) < 6) ) + { + return self::showActivationPage($key, _ERROR_PASSWORDTOOSHORT); + } + + if ( $password ) + { + $pwdvalid = true; + $pwderror = ''; + + $data = array( + 'password' => $password, + 'errormessage' => &$pwderror, + 'valid' => &$pwdvalid + ); + $manager->notify('PrePasswordSet', $data); + if ( !$pwdvalid ) + { + return self::showActivationPage($key,$pwderror); + } + } + + $error = ''; + + $data = array( + 'type' => 'activation', + 'member' => $mem, + 'error' => &$error + ); + $manager->notify('ValidateForm', $data); + if ( $error != '' ) + { + return self::showActivationPage($key, $error); + } + + // set password + $mem->setPassword($password); + $mem->write(); + + // do the activation + Member::activate($key); + + self::$skin->parse('activatesetpwd'); + return; + } + + /** + * Admin::action_manageteam() + * Manage team + * + * @param void + * @return void + */ + static private function action_manageteam() + { + global $member, $manager; + + $blogid = intRequestVar('blogid'); + + // check if allowed + $member->blogAdminRights($blogid) or self::disallow(); + + self::$skin->parse('manageteam'); + return; + } + + /** + * Admin::action_teamaddmember() + * Add member to team + * + * @param void + * @return void + */ + static private function action_teamaddmember() + { + global $member, $manager; + + $memberid = intPostVar('memberid'); + $blogid = intPostVar('blogid'); + $admin = intPostVar('admin'); + + // check if allowed + $member->blogAdminRights($blogid) or self::disallow(); + + $blog =& $manager->getBlog($blogid); + if ( !$blog->addTeamMember($memberid, $admin) ) + { + self::error(_ERROR_ALREADYONTEAM); + return; + } + + self::action_manageteam(); + return; + } + + /** + * Admin::action_teamdelete() + * + * @param void + * @return void + */ + static private function action_teamdelete() + { + global $member, $manager; + + $memberid = intRequestVar('memberid'); + $blogid = intRequestVar('blogid'); + + // check if allowed + $member->blogAdminRights($blogid) or self::disallow(); + + $teammem =& $manager->getMember($memberid); + $blog =& $manager->getBlog($blogid); + + self::$skin->parse('teamdelete'); + return; + } + + /** + * Admin::action_teamdeleteconfirm() + * + * @param void + * @return void + */ + static private function action_teamdeleteconfirm() + { + global $member; + + $memberid = intRequestVar('memberid'); + $blogid = intRequestVar('blogid'); + + $error = self::deleteOneTeamMember($blogid, $memberid); + if ( $error ) + { + self::error($error); + return; + } + self::action_manageteam(); + return; + } + + /** + * Admin::deleteOneTeamMember() + * + * @param void + * @return void + */ + static public function deleteOneTeamMember($blogid, $memberid) + { + global $member, $manager; + + $blogid = intval($blogid); + $memberid = intval($memberid); + + // check if allowed + if ( !$member->blogAdminRights($blogid) ) + { + return _ERROR_DISALLOWED; + } + + // check if: - there remains at least one blog admin + // - (there remains at least one team member) + $tmem =& $manager->getMember($memberid); + + + $data = array( + 'member' => &$tmem, + 'blogid' => $blogid + ); + $manager->notify('PreDeleteTeamMember', $data); + + if ( $tmem->isBlogAdmin($blogid) ) + { + /* TODO: why we did double check? */ + // check if there are more blog members left and at least one admin + // (check for at least two admins before deletion) + $query = "SELECT * FROM %s WHERE tblog=%d and tadmin=1;"; + $query = sprintf($query, sql_table('team'), (integer) $blogid); + $r = DB::getResult($query); + if ( $r->rowCount() < 2 ) + { + return _ERROR_ATLEASTONEBLOGADMIN; + } + } + + $query = "DELETE FROM %s WHERE tblog=%d AND tmember=%d;"; + $query = sprintf($query, sql_table('team'), (integer) $blogid, (integer) $memberid); + DB::execute($query); + + $data = array( + 'member' => &$tmem, + 'blogid' => $blogid + ); + $manager->notify('PostDeleteTeamMember', $data); + + return ''; + } + + /** + * Admin::action_teamchangeadmin() + * + * @param void + * @return void + */ + static private function action_teamchangeadmin() + { + global $manager, $member; + + $blogid = intRequestVar('blogid'); + $memberid = intRequestVar('memberid'); + + // check if allowed + $member->blogAdminRights($blogid) or self::disallow(); + + $mem =& $manager->getMember($memberid); + + // don't allow when there is only one admin at this moment + if ( $mem->isBlogAdmin($blogid) ) + { + $query = "SELECT * FROM %s WHERE tblog=%d AND tadmin=1;"; + $query = sprintf($query, sql_table('team'), (integer) $blogid); + $r = DB::getResult($query); + if ( $r->rowCount() == 1 ) + { + self::error(_ERROR_ATLEASTONEBLOGADMIN); + return; + } + } + + if ( $mem->isBlogAdmin($blogid) ) + { + $newval = 0; + } + else + { + $newval = 1; + } + + $query = "UPDATE %s SET tadmin=%d WHERE tblog=%d and tmember=%d;"; + $query = sprintf($query, (integer) $blogid, (integer) $newval, (integer) $blogid, (integer) $memberid); + DB::execute($query); + + // only show manageteam if member did not change its own admin privileges + if ( $member->isBlogAdmin($blogid) ) + { + self::action_manageteam(); + } + else + { + self::action_overview(_MSG_ADMINCHANGED); + } + return; + } + + /** + * Admin::action_blogsettings() + * + * @param void + * @return void + */ + static private function action_blogsettings() + { + global $member, $manager; + + $blogid = intRequestVar('blogid'); + + // check if allowed + $member->blogAdminRights($blogid) or self::disallow(); + + $blog =& $manager->getBlog($blogid); + + self::$extrahead .= "\n"; + + self::$skin->parse('blogsettings'); + return; + } + + /** + * Admin::action_categorynew() + * + * @param void + * @return void + */ + static private function action_categorynew() + { + global $member, $manager; + + $blogid = intRequestVar('blogid'); + + $member->blogAdminRights($blogid) or self::disallow(); + + $cname = postVar('cname'); + $cdesc = postVar('cdesc'); + + if ( !isValidCategoryName($cname) ) + { + self::error(_ERROR_BADCATEGORYNAME); + return; + } + + $query = "SELECT * FROM %s WHERE cname=%s AND cblog=%d;"; + $query = sprintf($query, sql_table('category'), DB::quoteValue($cname), (integer) $blogid); + $res = DB::getResult($query); + if ( $res->rowCount() > 0 ) + { + self::error(_ERROR_DUPCATEGORYNAME); + return; + } + + $blog =& $manager->getBlog($blogid); + $newCatID = $blog->createNewCategory($cname, $cdesc); + + self::action_blogsettings(); + return; + } + + /** + * Admin::action_categoryedit() + * + * @param void + * @return void + */ + static private function action_categoryedit($catid = '', $blogid = '', $desturl = '') + { + global $member, $manager; + + if ( $blogid == '' ) + { + $blogid = intGetVar('blogid'); + } + else + { + $blogid = intval($blogid); + } + if ( $catid == '' ) + { + $catid = intGetVar('catid'); + } + else + { + $catid = intval($catid); + } + + /* TODO: we should consider to use the other way insterad of this */ + $_REQUEST['blogid'] = $blogid; + $_REQUEST['catid'] = $catid; + $_REQUEST['desturl'] = $desturl; + $member->blogAdminRights($blogid) or self::disallow(); + + self::$extrahead .= "\n"; + + self::$skin->parse('categoryedit'); + return; + } + + /** + * Admin::action_categoryupdate() + * + * @param void + * @return void + */ + static private function action_categoryupdate() + { + global $member, $manager; + + $blogid = intPostVar('blogid'); + $catid = intPostVar('catid'); + $cname = postVar('cname'); + $cdesc = postVar('cdesc'); + $desturl = postVar('desturl'); + + $member->blogAdminRights($blogid) or self::disallow(); + + if ( !isValidCategoryName($cname) ) + { + self::error(_ERROR_BADCATEGORYNAME); + return; + } + + $query = "SELECT * FROM %s WHERE cname=%s AND cblog=%d AND not(catid=%d);"; + $query = sprintf($query, sql_table('category'), DB::quoteValue($cname), (integer) $blogid, (integer) $catid); + $res = DB::getResult($query); + if ( $res->rowCount() > 0 ) + { + self::error(_ERROR_DUPCATEGORYNAME); + return; + } + + $query = "UPDATE %s SET cname=%s, cdesc=%s WHERE catid=%d;"; + $query = sprintf($query, sql_table('category'), DB::quoteValue($cname), DB::quoteValue($cdesc), (integer) $catid); + DB::execute($query); + + // store plugin options + $aOptions = requestArray('plugoption'); + NucleusPlugin::apply_plugin_options($aOptions); + $data = array( + 'context' => 'category', + 'catid' => $catid + ); + $manager->notify('PostPluginOptionsUpdate', $data); + + if ( $desturl ) + { + redirect($desturl); + return; + } + + self::action_blogsettings(); + + return; + } + + /** + * Admin::action_categorydelete() + * + * @param void + * @return void + */ + static private function action_categorydelete() + { + global $member, $manager; + + $blogid = intRequestVar('blogid'); + $catid = intRequestVar('catid'); + + $member->blogAdminRights($blogid) or self::disallow(); + + $blog =& $manager->getBlog($blogid); + + // check if the category is valid + if ( !$blog->isValidCategory($catid) ) + { + self::error(_ERROR_NOSUCHCATEGORY); + return; + } + + // don't allow deletion of default category + if ( $blog->getDefaultCategory() == $catid ) + { + self::error(_ERROR_DELETEDEFCATEGORY); + return; + } + + // check if catid is the only category left for blogid + $query = "SELECT catid FROM %s WHERE cblog=%d;"; + $query = sprintf($query, sql_table('category'), $blogid); + $res = DB::getResult($query); + if ( $res->rowCount() == 1 ) + { + self::error(_ERROR_DELETELASTCATEGORY); + return; + } + + self::$skin->parse('categorydelete'); ++>>>>>>> skinnable-master + return; + } + + /** ++<<<<<<< HEAD ++ * Admin::action_browseownitems() ++======= + * Admin::action_categorydeleteconfirm() ++>>>>>>> skinnable-master + * + * @param void + * @return void + */ - static private function action_categorydeleteconfirm() ++<<<<<<< HEAD ++ public function action_browseownitems() + { - global $member, $manager; ++ global $member, $manager, $CONF; ++ ++ $this->pagehead(); ++ ++ echo '

(' . _BACKHOME . ")

\n"; ++ echo '

' . _ITEMLIST_YOUR . "

\n"; ++ ++ // start index ++ if ( postVar('start') ) ++ { ++ $start = intPostVar('start'); ++ } ++ else ++ { ++ $start = 0; ++ } ++ ++ // amount of items to show ++ if ( postVar('amount') ) ++ { ++ $amount = intPostVar('amount'); ++ } ++ else ++ { ++ $amount = (integer) $CONF['DefaultListSize']; ++ if ( $amount < 1 ) ++ { ++ $amount = 10; ++ } ++ } ++ ++ $search = postVar('search'); // search through items ++ ++ $query = 'SELECT bshortname, cname, mname, ititle, ibody, idraft, inumber, itime' ++ . ' FROM '.sql_table('item').', '.sql_table('blog') . ', '.sql_table('member') . ', '.sql_table('category') ++ . ' WHERE iauthor='. $member->getID() .' and iauthor=mnumber and iblog=bnumber and icat=catid'; ++ ++ if ( $search ) ++ { ++ $query .= " and ((ititle LIKE " . DB::quoteValue('%'.$search.'%') . ") or (ibody LIKE " . DB::quoteValue('%'.$search.'%') . ") or (imore LIKE " . DB::quoteValue('%'.$search.'%') . "))"; ++ } ++ ++ $query .= ' ORDER BY itime DESC' ++ . " LIMIT $start, $amount"; ++ ++ $template['content'] = 'itemlist'; ++ $template['now'] = time(); ++ ++ $manager->loadClass("ENCAPSULATE"); ++ $navList = new NavList('browseownitems', $start, $amount, 0, 1000, /*$blogid*/ 0, $search, 0); ++ $navList->showBatchList('item',$query,'table',$template); ++ ++ $this->pagefoot(); ++======= ++ static private function action_categorydeleteconfirm() ++ { ++ global $member, $manager; + + $blogid = intRequestVar('blogid'); + $catid = intRequestVar('catid'); + + $member->blogAdminRights($blogid) or self::disallow(); + + $error = self::deleteOneCategory($catid); + if ( $error ) + { + self::error($error); + return; + } + + self::action_blogsettings(); + return; + } + + /** + * Admin::deleteOneCategory() + * Delete a category by its id + * + * @param String $catid category id for deleting + * @return Void + */ + static public function deleteOneCategory($catid) + { + global $manager, $member; + + $catid = intval($catid); + $blogid = getBlogIDFromCatID($catid); + + if ( !$member->blogAdminRights($blogid) ) + { + return ERROR_DISALLOWED; + } + + // get blog + $blog =& $manager->getBlog($blogid); + + // check if the category is valid + if ( !$blog || !$blog->isValidCategory($catid) ) + { + return _ERROR_NOSUCHCATEGORY; + } + + $destcatid = $blog->getDefaultCategory(); + + // don't allow deletion of default category + if ( $blog->getDefaultCategory() == $catid ) + { + return _ERROR_DELETEDEFCATEGORY; + } + + // check if catid is the only category left for blogid + $query = "SELECT catid FROM %s WHERE cblog=%d;"; + $query = sprintf($query, sql_table('category'), (integer) $blogid); + + $res = DB::getResult($query); + if ( $res->rowCount() == 1 ) + { + return _ERROR_DELETELASTCATEGORY; + } + + $data = array('catid' => $catid); + $manager->notify('PreDeleteCategory', $data); + + // change category for all items to the default category + $query = "UPDATE %s SET icat=%d WHERE icat=%d;"; + $query =sprintf($query, sql_table('item'), (integer) $destcatid, (integer) $catid); + DB::execute($query); + + // delete all associated plugin options + NucleusPlugin::delete_option_values('category', (integer) $catid); + + // delete category + $query = "DELETE FROM %s WHERE catid=%d;"; + $query = sprintf($query, sql_table('category'), (integer) $catid); + DB::execute($query); + + $data = array('catid' => $catid); + $manager->notify('PostDeleteCategory', $data); ++>>>>>>> skinnable-master + return; + } + + /** ++<<<<<<< HEAD ++ * Admin::action_itemcommentlist() ++ * ++ * Show all the comments for a given item ++ * @param integer $itemid ID for item ++ * @return void ++ */ ++ public function action_itemcommentlist($itemid = '') ++ { ++ global $member, $manager, $CONF; ++ ++ if ( $itemid == '' ) ++ { ++ $itemid = intRequestVar('itemid'); ++ } ++ ++ // only allow if user is allowed to alter item ++ $member->canAlterItem($itemid) or $this->disallow(); ++ ++ $blogid = getBlogIdFromItemId($itemid); ++ ++ $this->pagehead(); ++ ++ // start index ++ if ( postVar('start') ) ++ { ++ $start = intPostVar('start'); ++ } ++ else ++ { ++ $start = 0; ++ } ++ ++ // amount of items to show ++ if ( postVar('amount') ) ++ { ++ $amount = intPostVar('amount'); ++ } ++ else ++ { ++ $amount = (integer) $CONF['DefaultListSize']; ++ if ( $amount < 1 ) ++ { ++ $amount = 10; ++ } ++ } ++ ++ $search = postVar('search'); ++ ++ echo '

(' . _BACKTOOVERVIEW . ")

\n"; ++ echo '

',_COMMENTS,'

'; ++ ++ $query = 'SELECT cbody, cuser, cmail, cemail, mname, ctime, chost, cnumber, cip, citem FROM ' . sql_table('comment') . ' LEFT OUTER JOIN ' . sql_table('member') . ' ON mnumber = cmember WHERE citem = ' . $itemid; ++ ++ if ( $search ) ++ { ++ $query .= " and cbody LIKE " . DB::quoteValue('%'.$search.'%'); ++ } ++ ++ $query .= ' ORDER BY ctime ASC' ++ . " LIMIT $start,$amount"; ++ ++ $template['content'] = 'commentlist'; ++ $template['canAddBan'] = $member->blogAdminRights(getBlogIDFromItemID($itemid)); ++ ++ $manager->loadClass("ENCAPSULATE"); ++ $navList = new NavList('itemcommentlist', $start, $amount, 0, 1000, 0, $search, $itemid); ++ $navList->showBatchList('comment',$query,'table',$template,_NOCOMMENTS); ++ ++ $this->pagefoot(); ++======= + * Admin::moveOneCategory() + * Delete a category by its id + * + * @param int $catid category id for move + * @param int $destblogid blog id for destination + * @return void + */ + static public function moveOneCategory($catid, $destblogid) + { + global $manager, $member; + $catid = intval($catid); + $destblogid = intval($destblogid); + $blogid = getBlogIDFromCatID($catid); + // mover should have admin rights on both blogs + if (!$member->blogAdminRights($blogid)) { + return _ERROR_DISALLOWED; + } + if (!$member->blogAdminRights($destblogid)) { + return _ERROR_DISALLOWED; + } + // cannot move to self + if ($blogid == $destblogid) { + return _ERROR_MOVETOSELF; + } + // get blogs + $blog =& $manager->getBlog($blogid); + $destblog =& $manager->getBlog($destblogid); + // check if the category is valid + if (!$blog || !$blog->isValidCategory($catid)) { + return _ERROR_NOSUCHCATEGORY; + } + // don't allow default category to be moved + if ($blog->getDefaultCategory() == $catid) { + return _ERROR_MOVEDEFCATEGORY; + } + $data = array( + 'catid' => &$catid, + 'sourceblog' => &$blog, + 'destblog' => &$destblog + ); + $manager->notify('PreMoveCategory', $data); + // update comments table (cblog) + $query = 'SELECT ' + . ' inumber ' + . 'FROM ' + . sql_table('item') . ' ' + . 'WHERE ' + . ' icat = %d'; + $items = sql_query(sprintf($query, $catid)); + while ($oItem = sql_fetch_object($items)) { + $query = 'UPDATE ' + . sql_table('comment') . ' ' + . 'SET ' + . ' cblog = %d' . ' ' + . 'WHERE ' + . ' citem = %d'; + sql_query(sprintf($query, $destblogid, $oItem->inumber)); + } + + // update items (iblog) + $query = 'UPDATE ' + . sql_table('item') . ' ' + . 'SET ' + . ' iblog = %d ' + . 'WHERE ' + . ' icat = %d'; + sql_query(sprintf($query, $destblogid, $catid)); + + // move category + $query = 'UPDATE ' + . sql_table('category') . ' ' + . 'SET ' + . ' cblog = %d' . ' ' + . 'WHERE ' + . ' catid = %d'; + sql_query(sprintf($query, $destblogid, $catid)); + + $data = array( + 'catid' => &$catid, + 'sourceblog' => &$blog, + 'destblog' => $destblog + ); + $manager->notify('PostMoveCategory', $data); + return; + } + + /** + * Admin::action_blogsettingsupdate + * Updating blog settings + * + * @param Void + * @return Void + */ + static private function action_blogsettingsupdate() + { + global $member, $manager; + + $blogid = intRequestVar('blogid'); + + $member->blogAdminRights($blogid) or self::disallow(); + + $blog =& $manager->getBlog($blogid); + + $notify_address = trim(postVar('notify')); + $shortname = trim(postVar('shortname')); + $updatefile = trim(postVar('update')); + + $notifyComment = intPostVar('notifyComment'); + $notifyVote = intPostVar('notifyVote'); + $notifyNewItem = intPostVar('notifyNewItem'); + + if ( $notifyComment == 0 ) + { + $notifyComment = 1; + } + if ( $notifyVote == 0 ) + { + $notifyVote = 1; + } + if ( $notifyNewItem == 0 ) + { + $notifyNewItem = 1; + } + $notifyType = $notifyComment * $notifyVote * $notifyNewItem; + + if ( $notify_address && !NOTIFICATION::address_validation($notify_address) ) + { + self::error(_ERROR_BADNOTIFY); + return; + } + + if ( !isValidShortName($shortname) ) + { + self::error(_ERROR_BADSHORTBLOGNAME); + return; + } + + if ( ($blog->getShortName() != $shortname) && $manager->existsBlog($shortname) ) + { + self::error(_ERROR_DUPSHORTBLOGNAME); + return; + } + // check if update file is writable + if ( $updatefile && !is_writeable($updatefile) ) + { + self::error(_ERROR_UPDATEFILE); + return; + } + + $blog->setName(trim(postVar('name'))); + $blog->setShortName($shortname); + $blog->setNotifyAddress($notify_address); + $blog->setNotifyType($notifyType); + $blog->setMaxComments(postVar('maxcomments')); + $blog->setCommentsEnabled(postVar('comments')); + $blog->setTimeOffset(postVar('timeoffset')); + $blog->setUpdateFile($updatefile); + $blog->setURL(trim(postVar('url'))); + $blog->setDefaultSkin(intPostVar('defskin')); + $blog->setDescription(trim(postVar('desc'))); + $blog->setPublic(postVar('public')); + $blog->setConvertBreaks(intPostVar('convertbreaks')); + $blog->setAllowPastPosting(intPostVar('allowpastposting')); + $blog->setDefaultCategory(intPostVar('defcat')); + $blog->setSearchable(intPostVar('searchable')); + $blog->setEmailRequired(intPostVar('reqemail')); + $blog->writeSettings(); + + // store plugin options + $aOptions = requestArray('plugoption'); + NucleusPlugin::apply_plugin_options($aOptions); + + $data = array( + 'context' => 'blog', + 'blogid' => $blogid, + 'blog' => &$blog + ); + $manager->notify('PostPluginOptionsUpdate', $data); + + self::action_overview(_MSG_SETTINGSCHANGED); ++>>>>>>> skinnable-master + return; + } + + /** ++<<<<<<< HEAD ++ * Admin::action_browseowncomments() ++ * Browse own comments ++======= + * Admin::action_deleteblog() ++>>>>>>> skinnable-master + * + * @param void + * @return void + */ ++<<<<<<< HEAD ++ public function action_browseowncomments() ++ { ++ global $member, $manager, $CONF; ++ ++ // start index ++ if ( postVar('start') ) ++ { ++ $start = intPostVar('start'); ++ } ++ else ++ { ++ $start = 0; ++ } ++ ++ // amount of items to show ++ if ( postVar('amount') ) ++ { ++ $amount = intPostVar('amount'); ++ } ++ else ++ { ++ $amount = intval($CONF['DefaultListSize']); ++ if ( $amount < 1 ) ++ { ++ $amount = 10; ++ } ++ } ++ ++ $search = postVar('search'); ++ ++ $query = 'SELECT cbody, cuser, cmail, mname, ctime, chost, cnumber, cip, citem FROM '.sql_table('comment').' LEFT OUTER JOIN '.sql_table('member').' ON mnumber=cmember WHERE cmember=' . $member->getID(); ++ ++ if ( $search ) ++ { ++ $query .= " and cbody LIKE " . DB::quoteValue('%'.$search.'%'); ++ } ++ ++ $query .= ' ORDER BY ctime DESC' ++ . " LIMIT $start,$amount"; ++ ++ $this->pagehead(); ++ ++ echo '

(' . _BACKHOME . ")

\n"; ++ echo '

' . _COMMENTS_YOUR . "

\n"; ++ ++ $template['content'] = 'commentlist'; ++ $template['canAddBan'] = 0; // doesn't make sense to allow banning yourself ++ ++ $manager->loadClass("ENCAPSULATE"); ++ $navList = new NavList('browseowncomments', $start, $amount, 0, 1000, 0, $search, 0); ++ $navList->showBatchList('comment',$query,'table',$template,_NOCOMMENTS_YOUR); ++ ++ $this->pagefoot(); ++======= + static private function action_deleteblog() + { + global $member, $CONF, $manager; + + $blogid = intRequestVar('blogid'); + + $member->blogAdminRights($blogid) or self::disallow(); + + // check if blog is default blog + if ( $CONF['DefaultBlog'] == $blogid ) + { + self::error(_ERROR_DELDEFBLOG); + return; + } + + $blog =& $manager->getBlog($blogid); + + self::$skin->parse('deleteblog'); + return; + } + + /** + * Admin::action_deleteblogconfirm() + * Delete Blog + * + * @param Void + * @return Void + */ + static private function action_deleteblogconfirm() + { + global $member, $CONF, $manager; + + $blogid = intRequestVar('blogid'); + + $data = array('blogid' => $blogid); + $manager->notify('PreDeleteBlog', $data); + + $member->blogAdminRights($blogid) or self::disallow(); + + // check if blog is default blog + if ( $CONF['DefaultBlog'] == $blogid ) + { + self::error(_ERROR_DELDEFBLOG); + return; + } + + // delete all comments + $query = 'DELETE FROM ' . sql_table('comment') . ' WHERE cblog='.$blogid; + DB::execute($query); + + // delete all items + $query = 'DELETE FROM ' . sql_table('item') . ' WHERE iblog=' . $blogid; + DB::execute($query); + + // delete all team members + $query = 'DELETE FROM ' . sql_table('team') . ' WHERE tblog=' . $blogid; + DB::execute($query); + + // delete all bans + $query = 'DELETE FROM ' . sql_table('ban') . ' WHERE blogid=' . $blogid; + DB::execute($query); + + // delete all categories + $query = 'DELETE FROM ' . sql_table('category') . ' WHERE cblog=' . $blogid; + DB::execute($query); + + // delete all associated plugin options + NucleusPlugin::delete_option_values('blog', $blogid); + + // delete the blog itself + $query = 'DELETE FROM ' . sql_table('blog') . ' WHERE bnumber=' . $blogid; + DB::execute($query); + + $data = array('blogid' => $blogid); + $manager->notify('PostDeleteBlog', $data); + + self::action_overview(_DELETED_BLOG); ++>>>>>>> skinnable-master + return; + } + + /** ++<<<<<<< HEAD ++ * Admin::action_blogcommentlist() ++ * ++ * Browse all comments for a weblog ++ * @param integer $blogid ID for weblog ++ * @return void ++ */ ++ function action_blogcommentlist($blogid = '') ++ { ++ global $member, $manager, $CONF; ++ ++ if ( $blogid == '' ) ++ { ++ $blogid = intRequestVar('blogid'); ++ } ++ else ++ { ++ $blogid = intval($blogid); ++ } ++ ++ $member->teamRights($blogid) or $member->isAdmin() or $this->disallow(); ++ ++ // start index ++ if ( postVar('start') ) ++ { ++ $start = intPostVar('start'); ++ } ++ else ++ { ++ $start = 0; ++ } ++ ++ // amount of items to show ++ if ( postVar('amount') ) ++ { ++ $amount = intPostVar('amount'); ++ } ++ else ++ { ++ $amount = intval($CONF['DefaultListSize']); ++ if ( $amount < 1 ) ++ { ++ $amount = 10; ++ } ++ } ++ ++ $search = postVar('search'); // search through comments ++ ++ $query = 'SELECT cbody, cuser, cemail, cmail, mname, ctime, chost, cnumber, cip, citem FROM '.sql_table('comment').' LEFT OUTER JOIN '.sql_table('member').' ON mnumber=cmember WHERE cblog=' . intval($blogid); ++ ++ if ( $search != '' ) ++ { ++ $query .= " and cbody LIKE " . DB::quoteValue('%'.$search.'%'); ++ } ++ ++ $query .= ' ORDER BY ctime DESC' ++ . " LIMIT $start,$amount"; ++ ++ $blog =& $manager->getBlog($blogid); ++ ++ $this->pagehead(); ++ ++ echo '

(' . _BACKHOME . ")

\n"; ++ echo '

', _COMMENTS_BLOG , ' ' , $this->bloglink($blog), '

'; ++ ++ $template['content'] = 'commentlist'; ++ $template['canAddBan'] = $member->blogAdminRights($blogid); ++ ++ $manager->loadClass("ENCAPSULATE"); ++ $navList = new NavList('blogcommentlist', $start, $amount, 0, 1000, $blogid, $search, 0); ++ $navList->showBatchList('comment',$query,'table',$template, _NOCOMMENTS_BLOG); ++ ++ $this->pagefoot(); ++======= + * Admin::action_memberdelete() + * + * @param void + * @return void + */ + static private function action_memberdelete() + { + global $member, $manager; + + $memberid = intRequestVar('memberid'); + + ($member->getID() == $memberid) or $member->isAdmin() or self::disallow(); + + $mem =& $manager->getMember($memberid); + + self::$skin->parse('memberdelete'); + return; + } + + /** + * Admin::action_memberdeleteconfirm() + * + * @param void + * @return void + */ + static private function action_memberdeleteconfirm() + { + global $member; + + $memberid = intRequestVar('memberid'); + + ($member->getID() == $memberid) or $member->isAdmin() or self::disallow(); + + $error = self::deleteOneMember($memberid); + if ( $error ) + { + self::error($error); + return; + } + + if ( $member->isAdmin() ) + { + self::action_usermanagement(); + return; + } + else + { + self::action_overview(_DELETED_MEMBER); + return; + } + return; + } + + /** + * Admin::deleteOneMember() + * Delete a member by id + * + * @static + * @params Integer $memberid member id + * @return String null string or error messages + */ + static public function deleteOneMember($memberid) + { + global $manager; + + $memberid = intval($memberid); + $mem =& $manager->getMember($memberid); + + if ( !$mem->canBeDeleted() ) + { + return _ERROR_DELETEMEMBER; + } + + $data = array('member' => &$mem); + $manager->notify('PreDeleteMember', $data); + + /* unlink comments from memberid */ + if ( $memberid ) + { + $query = "UPDATE %s SET cmember=0, cuser=%s WHERE cmember=%d;"; + $query = sprintf($query, sql_table('comment'), DB::quoteValue($mem->getDisplayName()), $memberid); + DB::execute($query); + } + + $query = 'DELETE FROM ' . sql_table('member') . ' WHERE mnumber=' . $memberid; + DB::execute($query); + + $query = 'DELETE FROM ' . sql_table('team') . ' WHERE tmember=' . $memberid; + DB::execute($query); + + $query = 'DELETE FROM ' . sql_table('activation') . ' WHERE vmember=' . $memberid; + DB::execute($query); + + // delete all associated plugin options + NucleusPlugin::delete_option_values('member', $memberid); + + $data = array('member' => &$mem); + $manager->notify('PostDeleteMember', $data); + + return ''; + } + + /** + * Admin::action_createnewlog() + * + * @param void + * @return void + */ + static private function action_createnewlog() + { + global $member, $CONF, $manager; + + // Only Super-Admins can do this + $member->isAdmin() or self::disallow(); + + self::$skin->parse('createnewlog'); + return; + } + + /** + * Admin::action_addnewlog() + * + * @param void + * @return void + */ + static private function action_addnewlog() + { + global $member, $manager, $CONF; + + // Only Super-Admins can do this + $member->isAdmin() or self::disallow(); + + $bname = trim(postVar('name')); + $bshortname = trim(postVar('shortname')); + $btimeoffset = postVar('timeoffset'); + $bdesc = trim(postVar('desc')); + $bdefskin = postVar('defskin'); + + if ( !isValidShortName($bshortname) ) + { + self::error(_ERROR_BADSHORTBLOGNAME); + return; + } + + if ( $manager->existsBlog($bshortname) ) + { + self::error(_ERROR_DUPSHORTBLOGNAME); + return; + } + + $data = array( + 'name' => &$bname, + 'shortname' => &$bshortname, + 'timeoffset' => &$btimeoffset, + 'description' => &$bdesc, + 'defaultskin' => &$bdefskin + ); + $manager->notify('PreAddBlog', $data); + + // add slashes for sql queries + $bname = DB::quoteValue($bname); + $bshortname = DB::quoteValue($bshortname); + $btimeoffset = DB::quoteValue($btimeoffset); + $bdesc = DB::quoteValue($bdesc); + $bdefskin = DB::quoteValue($bdefskin); + + // create blog + $query = "INSERT INTO %s (bname, bshortname, bdesc, btimeoffset, bdefskin) VALUES (%s, %s, %s, %s, %s);"; + $query = sprintf($query, sql_table('blog'), $bname, $bshortname, $bdesc, $btimeoffset, $bdefskin); + DB::execute($query); + + $blogid = DB::getInsertId(); + $blog =& $manager->getBlog($blogid); + + // create new category + $catdefname = (!defined('_EBLOGDEFAULTCATEGORY_NAME') ? 'General' : _EBLOGDEFAULTCATEGORY_NAME); + $catdefdesc = (!defined('_EBLOGDEFAULTCATEGORY_DESC') ? 'Items that do not fit in other categories' : _EBLOGDEFAULTCATEGORY_DESC); + + $query = 'INSERT INTO %s (cblog, cname, cdesc) VALUES (%d, %s, %s)'; + DB::execute(sprintf($query, sql_table('category'), (integer) $blogid, DB::quoteValue($catdefname), DB::quoteValue($catdefdesc))); + $catid = DB::getInsertId(); + + // set as default category + $blog->setDefaultCategory($catid); + $blog->writeSettings(); + + // create team member + $query = "INSERT INTO %s (tmember, tblog, tadmin) VALUES (%d, %d, 1);"; + $query = sprintf($query, sql_table('team'), (integer) $member->getID(), (integer) $blogid); + DB::execute($query); + + $itemdeftitle = (defined('_EBLOG_FIRSTITEM_TITLE') ? _EBLOG_FIRSTITEM_TITLE : 'First Item'); + $itemdefbody = (defined('_EBLOG_FIRSTITEM_BODY') ? _EBLOG_FIRSTITEM_BODY : 'This is the first item in your weblog. Feel free to delete it.'); + + $blog->additem( + $blog->getDefaultCategory(), + $itemdeftitle,$itemdefbody, + '', + $blogid, + $member->getID(), + $blog->getCorrectTime(), + 0, + 0, + 0 + ); + + $data = array('blog' => &$blog); + $manager->notify('PostAddBlog', $data); + + $data = array( + 'blog' => &$blog, + 'name' => _EBLOGDEFAULTCATEGORY_NAME, + 'description' => _EBLOGDEFAULTCATEGORY_DESC, + 'catid' => $catid + ); + $manager->notify('PostAddCategory', $data); + + /* TODO: we should consider to use the other way insterad of this */ + $_REQUEST['blogid'] = $blogid; + $_REQUEST['catid'] = $catid; + self::$skin->parse('addnewlog'); ++>>>>>>> skinnable-master + return; + } + + /** ++<<<<<<< HEAD ++ * Admin::action_createitem() ++ * Provide a page to item a new item to the given blog ++======= + * Admin::action_addnewlog2() ++>>>>>>> skinnable-master + * + * @param void + * @return void + */ ++<<<<<<< HEAD ++ public function action_createitem() ++ { ++ global $member, $manager; ++ ++ $blogid = intRequestVar('blogid'); ++ ++ // check if allowed ++ $member->teamRights($blogid) or $this->disallow(); ++ ++ $memberid = $member->getID(); ++ ++ $blog =& $manager->getBlog($blogid); ++ ++ // generate the add-item form ++ $handler = new PageFactory($blog); ++ ++ $contents = $handler->getTemplateFor('admin', 'add'); ++ $manager->notify('PreAddItemForm', array('contents' => &$contents, 'blog' => &$blog)); ++ ++ $parser = new Parser($handler); ++ ++ $this->pagehead(); ++ $parser->parse($contents); ++ $this->pagefoot(); ++ ++======= + static private function action_addnewlog2() + { + global $member, $manager; + $blogid = intRequestVar('blogid'); + + $member->blogAdminRights($blogid) or self::disallow(); + + $burl = requestVar('url'); + + $blog =& $manager->getBlog($blogid); + $blog->setURL(trim($burl)); + $blog->writeSettings(); + + self::action_overview(_MSG_NEWBLOG); + return; + } + + /** + * Admin::action_skinieoverview() + * + * @param void + * @return void + */ + static private function action_skinieoverview() + { + global $member, $DIR_LIBS, $manager; + + $member->isAdmin() or self::disallow(); + + include_once($DIR_LIBS . 'skinie.php'); + + self::$skin->parse('skinieoverview'); ++>>>>>>> skinnable-master + return; + } + + /** ++<<<<<<< HEAD ++ * Admin::action_itemedit() ++======= + * Admin::action_skinieimport() ++>>>>>>> skinnable-master + * + * @param void + * @return void + */ ++<<<<<<< HEAD ++ public function action_itemedit() ++ { ++ global $member, $manager; ++ ++ $itemid = intRequestVar('itemid'); ++ ++ // only allow if user is allowed to alter item ++ $member->canAlterItem($itemid) or $this->disallow(); ++ ++ $variables =& $manager->getItem($itemid, 1, 1); ++ $blog =& $manager->getBlog(getBlogIDFromItemID($itemid)); ++ ++ $manager->notify('PrepareItemForEdit', array('item' => &$variables)); ++ ++ if ( $blog->convertBreaks() ) ++ { ++ $variables['body'] = removeBreaks($variables['body']); ++ $variables['more'] = removeBreaks($variables['more']); ++ } ++ ++ // form to edit blog items ++ $handler = new PageFactory($blog); ++ $handler->setVariables($variables); ++ ++ $content = $handler->getTemplateFor('admin', 'edit'); ++ ++ $parser = new Parser($handler); ++ ++ $this->pagehead(); ++ $parser->parse($content); ++ $this->pagefoot(); ++ return; ++ } ++ ++ /** ++ * @todo document this ++ */ ++ function action_itemupdate() { ++ global $member, $manager, $CONF; ++ ++ $itemid = intRequestVar('itemid'); ++ $catid = postVar('catid'); ++ ++ // only allow if user is allowed to alter item ++ $member->canUpdateItem($itemid, $catid) or $this->disallow(); ++ + $actiontype = postVar('actiontype'); + + // delete actions are handled by itemdelete (which has confirmation) + if ($actiontype == 'delete') { + $this->action_itemdelete(); + return; + } + + $body = postVar('body'); + $title = postVar('title'); + $more = postVar('more'); + $closed = intPostVar('closed'); + $draftid = intPostVar('draftid'); + + // default action = add now + if (!$actiontype) + $actiontype='addnow'; + + // create new category if needed + if ( i18n::strpos($catid,'newcat') === 0 ) { + // get blogid + list($blogid) = sscanf($catid,"newcat-%d"); + + // create + $blog =& $manager->getBlog($blogid); + $catid = $blog->createNewCategory(); + + // show error when sth goes wrong + if (!$catid) + $this->doError(_ERROR_CATCREATEFAIL); + } + + /* + set some variables based on actiontype + + actiontypes: + draft items -> addnow, addfuture, adddraft, delete + non-draft items -> edit, changedate, delete + + variables set: + $timestamp: set to a nonzero value for future dates or date changes + $wasdraft: set to 1 when the item used to be a draft item + $publish: set to 1 when the edited item is not a draft + */ + $blogid = getBlogIDFromItemID($itemid); + $blog =& $manager->getBlog($blogid); + + $wasdrafts = array('adddraft', 'addfuture', 'addnow'); + $wasdraft = in_array($actiontype, $wasdrafts) ? 1 : 0; + $publish = ($actiontype != 'adddraft' && $actiontype != 'backtodrafts') ? 1 : 0; + if ($actiontype == 'addfuture' || $actiontype == 'changedate') { + $timestamp = mktime(intPostVar('hour'), intPostVar('minutes'), 0, intPostVar('month'), intPostVar('day'), intPostVar('year')); + } else { + $timestamp =0; + } + + // edit the item for real + Item::update($itemid, $catid, $title, $body, $more, $closed, $wasdraft, $publish, $timestamp); + + $this->updateFuturePosted($blogid); + + if ($draftid > 0) { + // delete permission is checked inside Item::delete() + Item::delete($draftid); + } + + // show category edit window when we created a new category + // ($catid will then be a new category ID, while postVar('catid') will be 'newcat-x') + if ($catid != intPostVar('catid')) { + $this->action_categoryedit( + $catid, + $blog->getID(), + $CONF['AdminURL'] . 'index.php?action=itemlist&blogid=' . getBlogIDFromItemID($itemid) + ); + } else { + // TODO: set start item correctly for itemlist + $this->action_itemlist(getBlogIDFromItemID($itemid)); + } + } ++======= + static private function action_skinieimport() + { + global $member; + + $member->isAdmin() or self::disallow(); + + $skinFileRaw = postVar('skinfile'); + $mode = postVar('mode'); + + $error = self::skinieimport($mode, $skinFileRaw); + if ( $error ) + { + self::error($error); + return; + } + + self::$skin->parse('skinieimport'); + return; + } /** - * Admin::action_itemdelete() - * Delete item + * Admin::action_skiniedoimport() * - * @param Void - * @return Void + * @param void + * @return void + */ + static private function action_skiniedoimport() + { + global $member, $DIR_LIBS, $DIR_SKINS; + + $member->isAdmin() or self::disallow(); + + // load skinie class + include_once($DIR_LIBS . 'skinie.php'); + + $mode = postVar('mode'); + $skinFileRaw = postVar('skinfile'); + $allowOverwrite = intPostVar('overwrite'); + + $error = self::skiniedoimport($mode, $skinFileRaw, $allowOverwrite); + if ( $error ) + { + self::error($msg); + return; + } + + self::$skin->parse('skiniedoimport'); + return; + } + + /** + * Admin::action_skinieexport() + * + * @param void + * @return void */ - function action_itemdelete() + static private function action_skinieexport() + { + global $member; + + $member->isAdmin() or self::disallow(); + + $aSkins = requestIntArray('skin'); + $aTemplates = requestIntArray('template'); + $info = postVar('info'); + + self::skinieexport($aSkins, $aTemplates, $info); + + return; + } + + /** + * Admin::action_templateoverview() + * + * @param void + * @return void + */ + static private function action_templateoverview() { global $member, $manager; - $itemid = intRequestVar('itemid'); + $member->isAdmin() or self::disallow(); - // only allow if user is allowed to alter item - $member->canAlterItem($itemid) or $this->disallow(); + self::$skin->parse('templateoverview'); + return; + } + + /** + * Admin::action_templateedit() + * + * @param string $msg message for pageheader + * @return void + */ + static private function action_templateedit($msg = '') + { + global $member, $manager; + if ( $msg ) + { + self::$headMess = $msg; + } - if ( !$manager->existsItem($itemid,1,1) ) + $templateid = intRequestVar('templateid'); + + $member->isAdmin() or self::disallow(); + + self::$extrahead .= "\n"; + self::$extrahead .= "\n"; + + self::$skin->parse('templateedit'); + return; + } + + /** + * Admin::action_templateupdate() + * + * @param void + * @return void + */ + static private function action_templateupdate() + { + global $member,$manager; + + $templateid = intRequestVar('templateid'); + + $member->isAdmin() or self::disallow(); + + $name = postVar('tname'); + $desc = postVar('tdesc'); + + if ( !isValidTemplateName($name) ) + { + self::error(_ERROR_BADTEMPLATENAME); + return; + } + + if ( (Template::getNameFromId($templateid) != $name) && Template::exists($name) ) { - $this->error(_ERROR_NOSUCHITEM); + self::error(_ERROR_DUPTEMPLATENAME); + return; } - $item =& $manager->getItem($itemid,1,1); - $title = Entity::hsc(strip_tags($item['title'])); - $body = strip_tags($item['body']); - $body = Entity::hsc(Entity::shorten($body,300,'...')); + // 1. Remove all template parts + $query = "DELETE FROM %s WHERE tdesc=%d;"; + $query = sprintf($query, sql_table('template'), (integer) $templateid); + DB::execute($query); - $this->pagehead(); - echo '

' . _DELETE_CONFIRM . "

\n"; - echo '

' . _CONFIRMTXT_ITEM . "

\n"; - echo "
\n"; - echo "{$title}\n"; - echo "
\n"; - echo "{$body}\n"; - echo "
\n"; - echo "
\n"; - echo "
\n"; - echo "\n"; - echo $manager->addTicketHidden() . "\n"; - echo "\n"; - echo '\n"; - echo "
\n"; - echo "
\n"; - $this->pagefoot(); + // 2. Update description + $query = "UPDATE %s SET tdname=%s, tddesc=%s WHERE tdnumber=%d;"; + $query = sprintf($query, sql_table('template_desc'), DB::quoteValue($name), DB::quoteValue($desc), (integer) $templateid); + DB::execute($query); + + // 3. Add non-empty template parts + self::addToTemplate($templateid, 'ITEM_HEADER', postVar('ITEM_HEADER')); + self::addToTemplate($templateid, 'ITEM', postVar('ITEM')); + self::addToTemplate($templateid, 'ITEM_FOOTER', postVar('ITEM_FOOTER')); + self::addToTemplate($templateid, 'MORELINK', postVar('MORELINK')); + self::addToTemplate($templateid, 'EDITLINK', postVar('EDITLINK')); + self::addToTemplate($templateid, 'NEW', postVar('NEW')); + self::addToTemplate($templateid, 'COMMENTS_HEADER', postVar('COMMENTS_HEADER')); + self::addToTemplate($templateid, 'COMMENTS_BODY', postVar('COMMENTS_BODY')); + self::addToTemplate($templateid, 'COMMENTS_FOOTER', postVar('COMMENTS_FOOTER')); + self::addToTemplate($templateid, 'COMMENTS_CONTINUED', postVar('COMMENTS_CONTINUED')); + self::addToTemplate($templateid, 'COMMENTS_TOOMUCH', postVar('COMMENTS_TOOMUCH')); + self::addToTemplate($templateid, 'COMMENTS_AUTH', postVar('COMMENTS_AUTH')); + self::addToTemplate($templateid, 'COMMENTS_ONE', postVar('COMMENTS_ONE')); + self::addToTemplate($templateid, 'COMMENTS_MANY', postVar('COMMENTS_MANY')); + self::addToTemplate($templateid, 'COMMENTS_NONE', postVar('COMMENTS_NONE')); + self::addToTemplate($templateid, 'ARCHIVELIST_HEADER', postVar('ARCHIVELIST_HEADER')); + self::addToTemplate($templateid, 'ARCHIVELIST_LISTITEM', postVar('ARCHIVELIST_LISTITEM')); + self::addToTemplate($templateid, 'ARCHIVELIST_FOOTER', postVar('ARCHIVELIST_FOOTER')); + self::addToTemplate($templateid, 'BLOGLIST_HEADER', postVar('BLOGLIST_HEADER')); + self::addToTemplate($templateid, 'BLOGLIST_LISTITEM', postVar('BLOGLIST_LISTITEM')); + self::addToTemplate($templateid, 'BLOGLIST_FOOTER', postVar('BLOGLIST_FOOTER')); + self::addToTemplate($templateid, 'CATLIST_HEADER', postVar('CATLIST_HEADER')); + self::addToTemplate($templateid, 'CATLIST_LISTITEM', postVar('CATLIST_LISTITEM')); + self::addToTemplate($templateid, 'CATLIST_FOOTER', postVar('CATLIST_FOOTER')); + self::addToTemplate($templateid, 'DATE_HEADER', postVar('DATE_HEADER')); + self::addToTemplate($templateid, 'DATE_FOOTER', postVar('DATE_FOOTER')); + self::addToTemplate($templateid, 'FORMAT_DATE', postVar('FORMAT_DATE')); + self::addToTemplate($templateid, 'FORMAT_TIME', postVar('FORMAT_TIME')); + self::addToTemplate($templateid, 'SEARCH_HIGHLIGHT', postVar('SEARCH_HIGHLIGHT')); + self::addToTemplate($templateid, 'SEARCH_NOTHINGFOUND', postVar('SEARCH_NOTHINGFOUND')); + self::addToTemplate($templateid, 'POPUP_CODE', postVar('POPUP_CODE')); + self::addToTemplate($templateid, 'MEDIA_CODE', postVar('MEDIA_CODE')); + self::addToTemplate($templateid, 'IMAGE_CODE', postVar('IMAGE_CODE')); + + $data = array('fields' => array()); + $manager->notify('TemplateExtraFields', $data); + foreach ( $data['fields'] as $pfkey=>$pfvalue ) + { + foreach ( $pfvalue as $pffield => $pfdesc ) + { + self::addToTemplate($templateid, $pffield, postVar($pffield)); + } + } + + // jump back to template edit + self::action_templateedit(_TEMPLATE_UPDATED); return; } - /** - * @todo document this - */ - function action_itemdeleteconfirm() { - global $member; - - $itemid = intRequestVar('itemid'); - - // only allow if user is allowed to alter item - $member->canAlterItem($itemid) or $this->disallow(); - - // get blogid first - $blogid = getBlogIdFromItemId($itemid); - - // delete item (note: some checks will be performed twice) - $this->deleteOneItem($itemid); - - $this->action_itemlist($blogid); - } - - /** - * Deletes one item and returns error if something goes wrong - * @param int $itemid - */ - function deleteOneItem($itemid) { - global $member, $manager; - - // only allow if user is allowed to alter item (also checks if itemid exists) - if (!$member->canAlterItem($itemid)) - return _ERROR_DISALLOWED; - - // need to get blogid before the item is deleted - $blogid = getBlogIDFromItemId($itemid); - - $manager->loadClass('ITEM'); - Item::delete($itemid); - - // update blog's futureposted - $this->updateFuturePosted($blogid); - } - /** - * Admin::updateFuturePosted() - * Update a blog's future posted flag + * Admin::addToTemplate() * - * @param integer $blogid + * @param Integer $id ID for template + * @param String $partname parts name + * @param String $content template contents + * @return Integer record index + * + */ + static private function addToTemplate($id, $partname, $content) + { + // don't add empty parts: + if ( !trim($content) ) + { + return -1; + } + + $query = "INSERT INTO %s (tdesc, tpartname, tcontent) VALUES (%d, %s, %s);"; + $query = sprintf($query, sql_table('template'), (integer) $id, DB::quoteValue($partname), DB::quoteValue($content)); + if ( DB::execute($query) === FALSE ) + { + $err = DB::getError(); + exit(_ADMIN_SQLDIE_QUERYERROR . $err[2]); + } + return DB::getInsertId(); + } + + /** + * Admin::action_templatedelete() + * + * @param void + * @return void + */ + static private function action_templatedelete() + { + global $member, $manager; + + $member->isAdmin() or self::disallow(); + + $templateid = intRequestVar('templateid'); + // TODO: check if template can be deleted + + self::$skin->parse('templatedelete'); + return; + } ++>>>>>>> skinnable-master + + /** + * Admin::action_templatedeleteconfirm() + * + * @param void * @return void + */ + static private function action_templatedeleteconfirm() + { + global $member, $manager; + + $templateid = intRequestVar('templateid'); + + $member->isAdmin() or self::disallow(); + + $data = array('templateid' => $templateid); + $manager->notify('PreDeleteTemplate', $data); + + // 1. delete description + DB::execute('DELETE FROM ' . sql_table('template_desc') . ' WHERE tdnumber=' . $templateid); + + // 2. delete parts + DB::execute('DELETE FROM ' . sql_table('template') . ' WHERE tdesc=' . $templateid); + + + $data = array('templateid' => $templateid); + $manager->notify('PostDeleteTemplate', $data); + + self::action_templateoverview(); + return; + } + + /** + * Admin::action_templatenew() * + * @param void + * @return void */ - function updateFuturePosted($blogid) + static private function action_templatenew() { - global $manager; + global $member; - $blog =& $manager->getBlog($blogid); - $currenttime = $blog->getCorrectTime(time()); + $member->isAdmin() or self::disallow(); ++<<<<<<< HEAD + $query = "SELECT * FROM %s WHERE iblog=%d AND iposted=0 AND itime>%s"; + $query = sprintf($query, sql_table('item'), (integer) $blogid, DB::formatDateTime($currenttime)); + $result = DB::getResult($query); + + if ( $result->rowCount() > 0 ) ++======= + $name = postVar('name'); + $desc = postVar('desc'); + + if ( !isValidTemplateName($name) ) ++>>>>>>> skinnable-master { - $blog->setFuturePost(); + self::error(_ERROR_BADTEMPLATENAME); + return; } - else + + if ( Template::exists($name) ) { - $blog->clearFuturePost(); + self::error(_ERROR_DUPTEMPLATENAME); + return; } + + $newTemplateId = Template::createNew($name, $desc); + + self::action_templateoverview(); return; } ++<<<<<<< HEAD + + /** + * @todo document this + */ + function action_itemmove() { + global $member, $manager; + + $itemid = intRequestVar('itemid'); + + // only allow if user is allowed to alter item + $member->canAlterItem($itemid) or $this->disallow(); + + $item =& $manager->getItem($itemid,1,1); + + $this->pagehead(); + ?> +

+
+ + + + addTicketHidden(); + $this->selectBlogCategory('catid',$item['catid'],10,1); + ?> + + +
+ pagefoot(); + } + + /** + * @todo document this + */ + function action_itemmoveto() { + global $member, $manager; + + $itemid = intRequestVar('itemid'); + $catid = requestVar('catid'); + + // create new category if needed + if ( i18n::strpos($catid,'newcat') === 0 ) { + // get blogid + list($blogid) = sscanf($catid,'newcat-%d'); + + // create + $blog =& $manager->getBlog($blogid); + $catid = $blog->createNewCategory(); + + // show error when sth goes wrong + if (!$catid) + $this->doError(_ERROR_CATCREATEFAIL); + } + + // only allow if user is allowed to alter item + $member->canUpdateItem($itemid, $catid) or $this->disallow(); + + $old_blogid = getBlogIDFromItemId($itemid); + + Item::move($itemid, $catid); + + // set the futurePosted flag on the blog + $this->updateFuturePosted(getBlogIDFromItemId($itemid)); + + // reset the futurePosted in case the item is moved from one blog to another + $this->updateFuturePosted($old_blogid); + + if ($catid != intRequestVar('catid')) + $this->action_categoryedit($catid, $blog->getID()); + else + $this->action_itemlist(getBlogIDFromCatID($catid)); + } + + /** + * Moves one item to a given category (category existance should be checked by caller) + * errors are returned + * @param int $itemid + * @param int $destCatid category ID to which the item will be moved + */ + function moveOneItem($itemid, $destCatid) { + global $member; + + // only allow if user is allowed to move item + if (!$member->canUpdateItem($itemid, $destCatid)) + return _ERROR_DISALLOWED; + + Item::move($itemid, $destCatid); + } + + /** + * Adds a item to the chosen blog + */ + function action_additem() { + global $manager, $CONF; + + $manager->loadClass('ITEM'); + + $result = Item::createFromRequest(); + + if ($result['status'] == 'error') + $this->error($result['message']); + + $blogid = getBlogIDFromItemID($result['itemid']); + $blog =& $manager->getBlog($blogid); + $btimestamp = $blog->getCorrectTime(); + $item = $manager->getItem(intval($result['itemid']), 1, 1); + + if ($result['status'] == 'newcategory') { + $distURI = $manager->addTicketToUrl($CONF['AdminURL'] . 'index.php?action=itemList&blogid=' . intval($blogid)); + $this->action_categoryedit($result['catid'], $blogid, $distURI); + } else { + $methodName = 'action_itemList'; + call_user_func(array(&$this, $methodName), $blogid); + } + } + + /** + * Allows to edit previously made comments + **/ + function action_commentedit() { + + global $member, $manager; + + $commentid = intRequestVar('commentid'); + + $member->canAlterComment($commentid) or $this->disallow(); + + $comment = Comment::getComment($commentid); + + $manager->notify('PrepareCommentForEdit', array('comment' => &$comment) ); + + // change
to \n + $comment['body'] = str_replace('
', '', $comment['body']); + + // replaced eregi_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0 + /* original eregi_replace: eregi_replace("[^<]*", "\\1", $comment['body']) */ + + $comment['body'] = preg_replace("#[^<]*#i", "\\1", $comment['body']); + + $this->pagehead(); + + ?> +

+ +
+ + + addTicketHidden(); ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ pagefoot(); + } + + /** + * @todo document this + */ + function action_commentupdate() { + global $member, $manager; + + $commentid = intRequestVar('commentid'); + + $member->canAlterComment($commentid) or $this->disallow(); + + $url = postVar('url'); + $email = postVar('email'); + $body = postVar('body'); + + # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0 + # original eregi: eregi("[a-zA-Z0-9|\.,;:!\?=\/\\]{90,90}", $body) != FALSE + # important note that '\' must be matched with '\\\\' in preg* expressions + + // intercept words that are too long + if (preg_match('#[a-zA-Z0-9|\.,;:!\?=\/\\\\]{90,90}#', $body) != FALSE) ++======= + + /** + * Admin::action_templateclone() + * + * @param void + * @return void + */ + static private function action_templateclone() + { + global $member; + + $templateid = intRequestVar('templateid'); + + $member->isAdmin() or self::disallow(); + + // 1. read old template + $name = Template::getNameFromId($templateid); + $desc = Template::getDesc($templateid); + + // 2. create desc thing + $name = "cloned" . $name; + + // if a template with that name already exists: + if ( Template::exists($name) ) ++>>>>>>> skinnable-master { - $this->error(_ERROR_COMMENT_LONGWORD); + $i = 1; + while (Template::exists($name . $i)) + { + $i++; + } + $name .= $i; } - - // check length - if (i18n::strlen($body) < 3) + + $newid = Template::createNew($name, $desc); + + // 3. create clone + // go through parts of old template and add them to the new one + $query = "SELECT tpartname, tcontent FROM %s WHERE tdesc=%d;"; + $query = sprintf($query, sql_table('template'), (integer) $templateid); + + $res = DB::getResult($query); + foreach ( $res as $row) { - $this->error(_ERROR_COMMENT_NOCOMMENT); + self::addToTemplate($newid, $row['tpartname'], $row['tcontent']); } - - if (i18n::strlen($body) > 5000) + + self::action_templateoverview(); + return; + } + + /** + * Admin::action_admintemplateoverview() + * + * @param void + * @return void + */ + static private function action_admintemplateoverview() + { + global $member; + $member->isAdmin() or self::disallow(); + self::$skin->parse('admntemplateoverview'); + return; + } + + /** + * Admin::action_admintemplateedit() + * + * @param string $msg message for pageheader + * @return void + */ + static private function action_admintemplateedit($msg = '') + { + global $member, $manager; + if ( $msg ) { - $this->error(_ERROR_COMMENT_TOOLONG); + self::$headMess = $msg; } - $member->isAdmin() or self::disallow(); - ++<<<<<<< HEAD + + // prepare body + $body = Comment::prepareBody($body); + + // call plugins + $manager->notify('PreUpdateComment',array('body' => &$body)); + + $query = 'UPDATE ' . sql_table('comment') + . ' SET cmail = ' . DB::quoteValue($url) . ', cemail = ' . DB::quoteValue($email) . ', cbody = ' . DB::quoteValue($body) + . ' WHERE cnumber = ' . $commentid; + DB::execute($query); + + // get itemid + $res = DB::getValue('SELECT citem FROM '.sql_table('comment').' WHERE cnumber=' . $commentid); + $itemid = $res; + + if ($member->canAlterItem($itemid)) + $this->action_itemcommentlist($itemid); + else + $this->action_browseowncomments(); + + } ++======= ++ $member->isAdmin() or self::disallow(); ++ + self::$extrahead .= "\n"; + self::$extrahead .= '' . "\n"; + + self::$skin->parse('admintemplateedit'); + return; + } ++>>>>>>> skinnable-master /** - * Admin::action_commentdelete() - * Update comment + * Admin::action_admintemplateupdate() * - * @param Void - * @return Void + * @param void + * @return void */ - function action_commentdelete() + static private function action_admintemplateupdate() { global $member, $manager; + $templateid = intRequestVar('templateid'); + $member->isAdmin() or self::disallow(); + $name = postVar('tname'); + $desc = postVar('tdesc'); - $commentid = intRequestVar('commentid'); - $member->canAlterComment($commentid) or $this->disallow(); - $comment = Comment::getComment($commentid); - - $body = strip_tags($comment['body']); - $body = Entity::hsc(Entity::shorten($body, 300, '...')); - - if ( $comment['member'] ) + if ( !isValidTemplateName($name) ) { - $author = $comment['member']; + self::error(_ERROR_BADTEMPLATENAME); + return; } - else + + if ( (Template::getNameFromId($templateid) != $name) && Template::exists($name) ) { - $author = $comment['user']; + self::error(_ERROR_DUPTEMPLATENAME); + return; } - $this->pagehead(); + // 1. Remove all template parts + $query = "DELETE FROM %s WHERE tdesc=%d;"; + $query = sprintf($query, sql_table('template'), (integer) $templateid); + DB::execute($query); - echo '

' . _DELETE_CONFIRM . "

\n"; - echo '

' . _CONFIRMTXT_COMMENT . "

\n"; - echo "
\n"; - echo '' . _EDITC_WHO . ":{$author}
\n"; - echo '' . _EDITC_TEXT . ":{$body}\n"; - echo "
\n"; - echo "
\n"; - echo "
\n"; - echo "\n"; - echo $manager->addTicketHidden() . "\n"; - echo "\n"; - echo '\n"; - echo "
\n"; - echo "
\n"; - $this->pagefoot(); + // 2. Update description + $query = "UPDATE %s SET tdname=%s, tddesc=%s WHERE tdnumber=%d;"; + $query = sprintf($query, sql_table('template_desc'), DB::quoteValue($name), DB::quoteValue($desc), (integer) $templateid); + DB::execute($query); + + // 3. Add non-empty template parts + self::addToTemplate($templateid, 'NORMALSKINLIST_HEAD', postVar('NORMALSKINLIST_HEAD')); + self::addToTemplate($templateid, 'NORMALSKINLIST_BODY', postVar('NORMALSKINLIST_BODY')); + self::addToTemplate($templateid, 'NORMALSKINLIST_FOOT', postVar('NORMALSKINLIST_FOOT')); + self::addToTemplate($templateid, 'ADMIN_CUSTOMHELPLINK_ICON', postVar('ADMIN_CUSTOMHELPLINK_ICON')); + self::addToTemplate($templateid, 'ADMIN_CUSTOMHELPLINK_ANCHOR', postVar('ADMIN_CUSTOMHELPLINK_ANCHOR')); + self::addToTemplate($templateid, 'ADMIN_BLOGLINK', postVar('ADMIN_BLOGLINK')); + self::addToTemplate($templateid, 'ADMIN_BATCHLIST', postVar('ADMIN_BATCHLIST')); + self::addToTemplate($templateid, 'ACTIVATE_FORGOT_TITLE', postVar('ACTIVATE_FORGOT_TITLE')); + self::addToTemplate($templateid, 'ACTIVATE_FORGOT_TEXT', postVar('ACTIVATE_FORGOT_TEXT')); + self::addToTemplate($templateid, 'ACTIVATE_REGISTER_TITLE', postVar('ACTIVATE_REGISTER_TITLE')); + self::addToTemplate($templateid, 'ACTIVATE_REGISTER_TEXT', postVar('ACTIVATE_REGISTER_TEXT')); + self::addToTemplate($templateid, 'ACTIVATE_CHANGE_TITLE', postVar('ACTIVATE_CHANGE_TITLE')); + self::addToTemplate($templateid, 'ACTIVATE_CHANGE_TEXT', postVar('ACTIVATE_CHANGE_TEXT')); + self::addToTemplate($templateid, 'TEMPLATE_EDIT_EXPLUGNAME', postVar('TEMPLATE_EDIT_EXPLUGNAME')); + self::addToTemplate($templateid, 'TEMPLATE_EDIT_ROW_HEAD', postVar('TEMPLATE_EDIT_ROW_HEAD')); + self::addToTemplate($templateid, 'TEMPLATE_EDIT_ROW_TAIL', postVar('TEMPLATE_EDIT_ROW_TAIL')); + self::addToTemplate($templateid, 'SPECIALSKINLIST_HEAD', postVar('SPECIALSKINLIST_HEAD')); + self::addToTemplate($templateid, 'SPECIALSKINLIST_BODY', postVar('SPECIALSKINLIST_BODY')); + self::addToTemplate($templateid, 'SPECIALSKINLIST_FOOT', postVar('SPECIALSKINLIST_FOOT')); + self::addToTemplate($templateid, 'SYSTEMINFO_GDSETTINGS', postVar('SYSTEMINFO_GDSETTINGS')); + self::addToTemplate($templateid, 'BANLIST_DELETED_LIST', postVar('BANLIST_DELETED_LIST')); + self::addToTemplate($templateid, 'INSERT_PLUGOPTION_TITLE', postVar('INSERT_PLUGOPTION_TITLE')); + self::addToTemplate($templateid, 'INSERT_PLUGOPTION_BODY', postVar('INSERT_PLUGOPTION_BODY')); + self::addToTemplate($templateid, 'INPUTYESNO_TEMPLATE_ADMIN', postVar('INPUTYESNO_TEMPLATE_ADMIN')); + self::addToTemplate($templateid, 'INPUTYESNO_TEMPLATE_NORMAL', postVar('INPUTYESNO_TEMPLATE_NORMAL')); + self::addToTemplate($templateid, 'ADMIN_SPECIALSKINLIST_HEAD', postVar('ADMIN_SPECIALSKINLIST_HEAD')); + self::addToTemplate($templateid, 'ADMIN_SPECIALSKINLIST_BODY', postVar('ADMIN_SPECIALSKINLIST_BODY')); + self::addToTemplate($templateid, 'ADMIN_SPECIALSKINLIST_FOOT', postVar('ADMIN_SPECIALSKINLIST_FOOT')); + self::addToTemplate($templateid, 'SKINIE_EXPORT_LIST', postVar('SKINIE_EXPORT_LIST')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_SELECT_HEAD', postVar('SHOWLIST_LISTPLUG_SELECT_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_SELECT_BODY', postVar('SHOWLIST_LISTPLUG_SELECT_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_SELECT_FOOT', postVar('SHOWLIST_LISTPLUG_SELECT_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_MEMBLIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_MEMBLIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_MEMBLIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_MEMBLIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_MEMBLIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_MEMBLIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_TEAMLIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_TEAMLIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_TEAMLIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_TEAMLIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_TEAMLIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_TEAMLIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGLIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGLIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGLIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGLIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGLIST_GURL', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGLIST_GURL')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGEVENTLIST', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGEVENTLIST')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGNEDUPDATE', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGNEDUPDATE')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGIN_DEPEND', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGIN_DEPEND')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGIN_DEPREQ', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGIN_DEPREQ')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGLISTFALSE', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGLISTFALSE')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGLIST_ACTN', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGLIST_ACTN')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGLIST_ADMN', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGLIST_ADMN')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGLIST_HELP', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGLIST_HELP')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGOPTSETURL', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGOPTSETURL')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGLIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGLIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_POPTLIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_POPTLIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_POPTLIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_POPTLIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLGOPT_OYESNO', postVar('SHOWLIST_LISTPLUG_TABLE_PLGOPT_OYESNO')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLGOPT_OPWORD', postVar('SHOWLIST_LISTPLUG_TABLE_PLGOPT_OPWORD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLGOPT_OSELEP', postVar('SHOWLIST_LISTPLUG_TABLE_PLGOPT_OSELEP')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLGOPT_OSELEO', postVar('SHOWLIST_LISTPLUG_TABLE_PLGOPT_OSELEO')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLGOPT_OSELEC', postVar('SHOWLIST_LISTPLUG_TABLE_PLGOPT_OSELEC')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLGOPT_OTAREA', postVar('SHOWLIST_LISTPLUG_TABLE_PLGOPT_OTAREA')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLGOPT_OITEXT', postVar('SHOWLIST_LISTPLUG_TABLE_PLGOPT_OITEXT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_PLUGOPTN_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_PLUGOPTN_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_POPTLIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_POPTLIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_ITEMLIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_ITEMLIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_ITEMLIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_ITEMLIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_ITEMLIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_ITEMLIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_CMNTLIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_CMNTLIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_CMNTLIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_CMNTLIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_CMNTLIST_ABAN', postVar('SHOWLIST_LISTPLUG_TABLE_CMNTLIST_ABAN')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_CMNTLIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_CMNTLIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_BLOGLIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_BLOGLIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_BLOGLIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_BLOGLIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_BLIST_BD_TADM', postVar('SHOWLIST_LISTPLUG_TABLE_BLIST_BD_TADM')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_BLIST_BD_SADM', postVar('SHOWLIST_LISTPLUG_TABLE_BLIST_BD_SADM')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_BLOGLIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_BLOGLIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_BLOGSNAM_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_BLOGSNAM_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_BLOGSNAM_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_BLOGSNAM_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_BLOGSNAM_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_BLOGSNAM_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_SHORTNAM_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_SHORTNAM_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_SHORTNAM_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_SHORTNAM_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_SHORTNAM_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_SHORTNAM_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_CATELIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_CATELIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_CATELIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_CATELIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_CATELIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_CATELIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_TPLTLIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_TPLTLIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_TPLTLIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_TPLTLIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_TPLTLIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_TPLTLIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_SKINLIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_SKINLIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_SKINLIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_SKINLIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_SKINLIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_SKINLIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_DRFTLIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_DRFTLIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_DRFTLIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_DRFTLIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_DRFTLIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_DRFTLIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_ACTNLIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_ACTNLIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_ACTNLIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_ACTNLIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_ACTNLIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_ACTNLIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_IBANLIST_HEAD', postVar('SHOWLIST_LISTPLUG_TABLE_IBANLIST_HEAD')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_IBANLIST_BODY', postVar('SHOWLIST_LISTPLUG_TABLE_IBANLIST_BODY')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_IBANLIST_FOOT', postVar('SHOWLIST_LISTPLUG_TABLE_IBANLIST_FOOT')); + self::addToTemplate($templateid, 'SHOWLIST_LISTPLUG_TABLE_NAVILIST', postVar('SHOWLIST_LISTPLUG_TABLE_NAVILIST')); + self::addToTemplate($templateid, 'PLUGIN_QUICKMENU_TITLE', postVar('PLUGIN_QUICKMENU_TITLE')); + self::addToTemplate($templateid, 'PLUGIN_QUICKMENU_HEAD', postVar('PLUGIN_QUICKMENU_HEAD')); + self::addToTemplate($templateid, 'PLUGIN_QUICKMENU_BODY', postVar('PLUGIN_QUICKMENU_BODY')); + self::addToTemplate($templateid, 'PLUGIN_QUICKMENU_FOOT', postVar('PLUGIN_QUICKMENU_FOOT')); + + $data = array('fields' => array()); + $manager->notify('AdminTemplateExtraFields', $data); + foreach ( $data['fields'] as $pfkey => $pfvalue ) + { + foreach ( $pfvalue as $pffield => $pfdesc ) + { + self::addToTemplate($templateid, $pffield, postVar($pffield)); + } + } + + // jump back to template edit + self::action_admintemplateedit(_TEMPLATE_UPDATED); + return; + } + + /** + * Admin::action_admintemplatedelete() + * + * @param void + * @return void + */ + static private function action_admintemplatedelete() + { + global $member, $manager; + $member->isAdmin() or self::disallow(); + + // TODO: check if template can be deleted + self::$skin->parse('admintemplatedelete'); return; } ++<<<<<<< HEAD + /** + * @todo document this + */ + function action_commentdeleteconfirm() { + global $member; + + $commentid = intRequestVar('commentid'); + + // get item id first + $res = DB::getValue('SELECT citem FROM '.sql_table('comment') .' WHERE cnumber=' . $commentid); + $itemid = $res; + + $error = $this->deleteOneComment($commentid); + if ($error) + $this->doError($error); + + if ($member->canAlterItem($itemid)) + $this->action_itemcommentlist($itemid); + else + $this->action_browseowncomments(); + } + + /** + * @todo document this + */ + function deleteOneComment($commentid) { + global $member, $manager; + + $commentid = intval($commentid); + + if (!$member->canAlterComment($commentid)) + return _ERROR_DISALLOWED; + + $manager->notify('PreDeleteComment', array('commentid' => $commentid)); + + // delete the comments associated with the item + $query = 'DELETE FROM '.sql_table('comment').' WHERE cnumber=' . $commentid; + DB::execute($query); + + $manager->notify('PostDeleteComment', array('commentid' => $commentid)); + + return ''; + } + + /** + * Admin::action_usermanagement() + * + * Usermanagement main + * @param void + * @return void + */ + public function action_usermanagement() + { + global $member, $manager; + + // check if allowed + $member->isAdmin() or $this->disallow(); + + $this->pagehead(); + + echo '

(' . _BACKTOMANAGE . ")

\n"; + + echo '

' . _MEMBERS_TITLE . "

\n"; + + echo '

' . _MEMBERS_CURRENT . "

\n"; + + // show list of members with actions + $query = 'SELECT * FROM '.sql_table('member'); + $template['content'] = 'memberlist'; + $template['tabindex'] = 10; + + $manager->loadClass("ENCAPSULATE"); + $batch = new Batch('member'); + $batch->showlist($query,'table',$template); + + echo '

' . _MEMBERS_NEW .'

'; + echo "
\n"; + echo "
\n"; + echo "\n"; + $manager->addTicketHidden(); + + echo '' ."\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "
' . _MEMBERS_NEW . "
' . _MEMBERS_DISPLAY; + help('shortnames'); + echo '
'; + echo '' . _MEMBERS_DISPLAY_INFO . ''; + echo "
' . _MEMBERS_REALNAME . "
' . _MEMBERS_PWD . "
' . _MEMBERS_REPPWD . "
' . _MEMBERS_EMAIL . "
' . _MEMBERS_URL . "
' . _MEMBERS_SUPERADMIN; + help('superadmin'); + echo "'; + $this->input_yesno('admin',0,10060); + echo "
' . _MEMBERS_CANLOGIN; + help('canlogin'); + echo "'; + $this->input_yesno('canlogin',1,10070); + echo "
' . _MEMBERS_NOTES . "
' . _MEMBERS_NEW . "' . "
\n"; + echo "
\n"; + echo "
\n"; + $this->pagefoot(); + return; + } + + /** + * Edit member settings + */ + function action_memberedit() { + $this->action_editmembersettings(intRequestVar('memberid')); + } + ++======= ++>>>>>>> skinnable-master /** - * @todo document this + * Admin::action_admintemplatedeleteconfirm() + * + * @param void + * @return void */ - function action_editmembersettings($memberid = '') { - global $member, $manager, $CONF; + static private function action_admintemplatedeleteconfirm() + { + global $member, $manager; - if ($memberid == '') - { - $memberid = $member->getID(); - } + $templateid = intRequestVar('templateid'); + $member->isAdmin() or self::disallow(); - // check if allowed - ($member->getID() == $memberid) or $member->isAdmin() or $this->disallow(); + $data = array('templateid' => $templateid); + $manager->notify('PreDeleteAdminTemplate', $data); - $extrahead = ''; - $this->pagehead($extrahead); + // 1. delete description + $query = "DELETE FROM %s WHERE tdnumber=%s;"; + $query = sprintf($query, sql_table('template_desc'), (integer) $templateid); + DB::execute($query); ++<<<<<<< HEAD + // show message to go back to member overview (only for admins) + if ($member->isAdmin()) + { + echo '(' ._MEMBERS_BACKTOOVERVIEW. ')'; + } + else + { + echo '(' ._BACKHOME. ')'; + } + echo '

' . _MEMBERS_EDIT . '

'; + + $mem =& $manager->getMember($memberid); + ?> +
+ + + + addTicketHidden() ?> + + + + + + + + + + + isAdmin()) { ?> + + + + + + + + + + + + + isAdmin()) { + ?> + + + + + + + + + + + + + + + + + + + _insertPluginOptions('member',$memberid); + ?> + + + + + +
+
+
+ isAdmin()) { ?> + + getDisplayName()); + } + ?> +
+
+
input_yesno('admin',$mem->isAdmin(),60); ?>
input_yesno('canlogin',$mem->canLogin(),70,1,0,_YES,_NO,$mem->isAdmin()); ?>
+ + + + +
input_yesno('autosave', $mem->getAutosave(), 87); ?>
+ +
+ + ',_PLUGINS_EXTRA,''; + + $manager->notify( + 'MemberSettingsFormExtras', + array( + 'member' => &$mem + ) + ); + $this->pagefoot(); ++======= + // 2. delete parts + $query = "DELETE FROM %s WHERE tdesc=%d;"; + $query = sprintf($query, sql_table('template'), (integer) $templateid); + DB::execute($query); + + $data = array('templateid' => $templateid); + $manager->notify('PostDeleteAdminTemplate', $data); + + self::action_admintemplateoverview(); + return; ++>>>>>>> skinnable-master } - /** - * @todo document this - */ - function action_changemembersettings() { - global $member, $CONF, $manager; - - $memberid = intRequestVar('memberid'); - - // check if allowed - ($member->getID() == $memberid) or $member->isAdmin() or $this->disallow(); - - $name = trim(strip_tags(postVar('name'))); - $realname = trim(strip_tags(postVar('realname'))); - $password = postVar('password'); - $repeatpassword = postVar('repeatpassword'); - $email = strip_tags(postVar('email')); - $url = strip_tags(postVar('url')); - - # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0 - # original eregi: !eregi("^https?://", $url) - - // begin if: sometimes user didn't prefix the URL with http:// or https://, this cause a malformed URL. Let's fix it. - if (!preg_match('#^https?://#', $url) ) + /** + * Admin::action_admintemplatenew() + * + * @param void + * @return void + */ + static private function action_admintemplatenew() + { + global $member; + $member->isAdmin() or self::disallow(); + $name = postVar('name'); + $desc = postVar('desc'); + + if ( !isValidTemplateName($name) ) { ++<<<<<<< HEAD + $url = 'http://' . $url; + } + + $admin = postVar('admin'); + $canlogin = postVar('canlogin'); + $notes = strip_tags(postVar('notes')); + $locale = postVar('locale'); + + $mem =& $manager->getMember($memberid); + + if ($CONF['AllowLoginEdit'] || $member->isAdmin()) { + + if (!isValidDisplayName($name)) + $this->error(_ERROR_BADNAME); + + if (($name != $mem->getDisplayName()) && Member::exists($name)) + $this->error(_ERROR_NICKNAMEINUSE); + + if ($password != $repeatpassword) + $this->error(_ERROR_PASSWORDMISMATCH); + + if ($password && (i18n::strlen($password) < 6)) + $this->error(_ERROR_PASSWORDTOOSHORT); + + if ($password) { + $pwdvalid = true; + $pwderror = ''; + $manager->notify('PrePasswordSet',array('password' => $password, 'errormessage' => &$pwderror, 'valid' => &$pwdvalid)); + if (!$pwdvalid) { + $this->error($pwderror); + } + } ++======= + self::error(_ERROR_BADTEMPLATENAME); + return; ++>>>>>>> skinnable-master } - - if ( !NOTIFICATION::address_validation($email) ) + else if ( !preg_match('#^admin/#', $name) ) { - $this->error(_ERROR_BADMAILADDRESS); + self::error(_ERROR_BADADMINTEMPLATENAME); + return; } - if ( !$realname ) + else if ( Template::exists($name) ) { - $this->error(_ERROR_REALNAMEMISSING); + self::error(_ERROR_DUPTEMPLATENAME); + return; } ++<<<<<<< HEAD + if ( ($locale != '') && (!in_array($locale, i18n::get_available_locale_list())) ) + $this->error(_ERROR_NOSUCHTRANSLATION); + + // check if there will remain at least one site member with both the logon and admin rights + // (check occurs when taking away one of these rights from such a member) + if ( (!$admin && $mem->isAdmin() && $mem->canLogin()) + || (!$canlogin && $mem->isAdmin() && $mem->canLogin()) + ) + { + $r = DB::getResult('SELECT * FROM '.sql_table('member').' WHERE madmin=1 and mcanlogin=1'); + if ($r->rowCount() < 2) + $this->error(_ERROR_ATLEASTONEADMIN); + } + + if ($CONF['AllowLoginEdit'] || $member->isAdmin()) { + $mem->setDisplayName($name); + if ($password) + $mem->setPassword($password); + } + + $oldEmail = $mem->getEmail(); + + $mem->setRealName($realname); + $mem->setEmail($email); + $mem->setURL($url); + $mem->setNotes($notes); + $mem->setLocale($locale); + + + // only allow super-admins to make changes to the admin status + if ($member->isAdmin()) { + $mem->setAdmin($admin); + $mem->setCanLogin($canlogin); + } + + $autosave = postVar ('autosave'); + $mem->setAutosave($autosave); + + $mem->write(); + + // store plugin options + $aOptions = requestArray('plugoption'); + NucleusPlugin::apply_plugin_options($aOptions); + $manager->notify('PostPluginOptionsUpdate',array('context' => 'member', 'memberid' => $memberid, 'member' => &$mem)); + + // if email changed, generate new password + if ($oldEmail != $mem->getEmail()) + { + $mem->sendActivationLink('addresschange', $oldEmail); + // logout member + $mem->newCookieKey(); + + // only log out if the member being edited is the current member. + if ($member->getID() == $memberid) + $member->logout(); + $this->action_login(_MSG_ACTIVATION_SENT, 0); + return; + } + + + if ( ( $mem->getID() == $member->getID() ) + && ( $mem->getDisplayName() != $member->getDisplayName() ) + ) { + $mem->newCookieKey(); + $member->logout(); + $this->action_login(_MSG_LOGINAGAIN, 0); + } else { + $this->action_overview(_MSG_SETTINGSCHANGED); + } + } + ++======= + + $newTemplateId = Template::createNew($name, $desc); + self::action_admintemplateoverview(); + return; + } + ++>>>>>>> skinnable-master /** - * Admin::action_memberadd() + * Admin::action_admintemplateclone() * * @param void * @return void - * - */ - function action_memberadd() + */ + static private function action_admintemplateclone() { - global $member, $manager; + global $member; + $templateid = intRequestVar('templateid'); + $member->isAdmin() or self::disallow(); - // check if allowed - $member->isAdmin() or $this->disallow(); + // 1. read old template + $name = Template::getNameFromId($templateid); + $desc = Template::getDesc($templateid); - if ( postVar('password') != postVar('repeatpassword') ) + // 2. create desc thing + $name = $name . "cloned"; + + // if a template with that name already exists: + if ( Template::exists($name) ) { - $this->error(_ERROR_PASSWORDMISMATCH); + $i = 1; + while ( Template::exists($name . $i) ) + { + $i++; + } + $name .= $i; } - if ( i18n::strlen(postVar('password')) < 6 ) + $newid = Template::createNew($name, $desc); + + // 3. create clone + // go through parts of old template and add them to the new one + $query = "SELECT tpartname, tcontent FROM %s WHERE tdesc=%d;"; + $query = sprintf($query, sql_table('template'), (integer) $templateid); + + $res = DB::getResult($query); + foreach ( $res as $row ) { - $this->error(_ERROR_PASSWORDTOOSHORT); + self::addToTemplate($newid, $row['tpartname'], $row['tcontent']); } - $res = Member::create(postVar('name'), postVar('realname'), postVar('password'), postVar('email'), postVar('url'), postVar('admin'), postVar('canlogin'), postVar('notes')); - if ( $res != 1 ) + self::action_admintemplateoverview(); + return; + } + + /** + * Admin::action_skinoverview() + * + * @param void + * @return void + */ + static private function action_skinoverview() + { + global $member, $manager; + + $member->isAdmin() or self::disallow(); + + self::$skin->parse('skinoverview'); + return; + } + + /** + * Admin::action_skinnew() + * + * @param void + * @return void + */ + static private function action_skinnew() + { + global $member; + + $member->isAdmin() or self::disallow(); + + $name = trim(postVar('name')); + $desc = trim(postVar('desc')); + + if ( !isValidSkinName($name) ) + { + self::error(_ERROR_BADSKINNAME); + return; + } + else if ( SKIN::exists($name) ) { - $this->error($res); + self::error(_ERROR_DUPSKINNAME); + return; } - // fire PostRegister event - $newmem = new Member(); - $newmem->readFromName(postVar('name')); - $manager->notify('PostRegister',array('member' => &$newmem)); + SKIN::createNew($name, $desc); - $this->action_usermanagement(); + self::action_skinoverview(); return; } - ++<<<<<<< HEAD + + /** + * Account activation + * + * @author dekarma + */ + function action_activate() { + + $key = getVar('key'); + $this->_showActivationPage($key); + } + + /** + * @todo document this + */ + function _showActivationPage($key, $message = '') + { + global $manager; + + // clean up old activation keys + Member::cleanupActivationTable(); + + // get activation info + $info = Member::getActivationInfo($key); + + if (!$info) + $this->error(_ERROR_ACTIVATE); + + $mem =& $manager->getMember($info['vmember']); + + if (!$mem) + $this->error(_ERROR_ACTIVATE); + + $text = ''; + $title = ''; + $bNeedsPasswordChange = true; + + switch ($info['vtype']) + { + case 'forgot': + $title = _ACTIVATE_FORGOT_TITLE; + $text = _ACTIVATE_FORGOT_TEXT; + break; + case 'register': + $title = _ACTIVATE_REGISTER_TITLE; + $text = _ACTIVATE_REGISTER_TEXT; + break; + case 'addresschange': + $title = _ACTIVATE_CHANGE_TITLE; + $text = _ACTIVATE_CHANGE_TEXT; + $bNeedsPasswordChange = false; + Member::activate($key); + break; + } + + $aVars = array( + 'memberName' => Entity::hsc($mem->getDisplayName()) + ); + $title = Template::fill($title, $aVars); + $text = Template::fill($text, $aVars); + + $this->pagehead(); + + echo '

' , $title, '

'; + echo '

' , $text, '

'; + + if ($message != '') + { + echo '

',$message,'

'; + } + + if ($bNeedsPasswordChange) + { + ?> +
+ + + addTicketHidden() ?> + + + + + + + + + notify('FormExtra', array('type' => 'activation', 'member' => $mem)); + + ?> + + + +
+ + +
+ + pagefoot(); + + } + + /** + * Account activation - set password part + * + * @author dekarma + */ + function action_activatesetpwd() + { + global $manager; + $key = postVar('key'); + + // clean up old activation keys + Member::cleanupActivationTable(); + + // get activation info + $info = Member::getActivationInfo($key); + + if (!$info || ($info['type'] == 'addresschange')) + return $this->_showActivationPage($key, _ERROR_ACTIVATE); + + $mem =& $manager->getMember($info['vmember']); + + if (!$mem) + return $this->_showActivationPage($key, _ERROR_ACTIVATE); + + $password = postVar('password'); + $repeatpassword = postVar('repeatpassword'); + + if ($password != $repeatpassword) + return $this->_showActivationPage($key, _ERROR_PASSWORDMISMATCH); + + if ($password && (i18n::strlen($password) < 6)) + return $this->_showActivationPage($key, _ERROR_PASSWORDTOOSHORT); + + if ($password) { + $pwdvalid = true; + $pwderror = ''; + global $manager; + $manager->notify('PrePasswordSet',array('password' => $password, 'errormessage' => &$pwderror, 'valid' => &$pwdvalid)); + if (!$pwdvalid) { + return $this->_showActivationPage($key,$pwderror); + } + } + + $error = ''; + + $manager->notify('ValidateForm', array('type' => 'activation', 'member' => $mem, 'error' => &$error)); + if ($error != '') + return $this->_showActivationPage($key, $error); + + + // set password + $mem->setPassword($password); + $mem->write(); + + // do the activation + Member::activate($key); + + $this->pagehead(); + echo '

',_ACTIVATE_SUCCESS_TITLE,'

'; + echo '

',_ACTIVATE_SUCCESS_TEXT,'

'; + $this->pagefoot(); + } + /** - * Admin::action_skinedit() + * Admin::action_manageteam() * + * Manage team * @param void * @return void */ - static private function action_skinedit() + public function action_manageteam() { - global $member; + global $member, $manager; - $member->isAdmin() or self::disallow(); + $blogid = intRequestVar('blogid'); - self::$skin->parse('skinedit'); - return; - } - - /** - * Admin::action_skineditgeneral() - * - * @param void - * @return void - */ - static private function action_skineditgeneral() - { - global $member; + // check if allowed + $member->blogAdminRights($blogid) or $this->disallow(); - $skinid = intRequestVar('skinid'); + $this->pagehead(); - $member->isAdmin() or self::disallow(); + echo "

(" . _BACK_TO_BLOGSETTINGS . ")

\n"; - $error = self::skineditgeneral($skinid); - if ( $error ) - { - self::error($error); - return; - } + echo '

' . _TEAM_TITLE . getBlogNameFromID($blogid) . "

\n"; - self::action_skinedit(); - return; - } - - static private function action_skinedittype($msg = '') - { - global $member; + echo '

' . _TEAM_CURRENT . "

\n"; - $member->isAdmin() or self::disallow(); + $query = 'SELECT tblog, tmember, mname, mrealname, memail, tadmin' + . ' FROM '.sql_table('member').', '.sql_table('team') + . ' WHERE tmember=mnumber and tblog=' . $blogid; - if ( $msg ) - { - self::$headMess = $msg; - } + $template['content'] = 'teamlist'; + $template['tabindex'] = 10; - $type = requestVar('type'); - $type = trim($type); - $type = strtolower($type); + $manager->loadClass("ENCAPSULATE"); + $batch = new Batch('team'); + $batch->showlist($query, 'table', $template); - if ( !isValidShortName($type) ) - { - self::error(_ERROR_SKIN_PARTS_SPECIAL_FORMAT); - return; - } + echo '

' . _TEAM_ADDNEW . "

\n"; + + echo "
\n"; + echo "
\n"; - self::$skin->parse('skinedittype'); - return; - } + echo "\n"; + echo "\n"; + $manager->addTicketHidden(); + + echo '' . "\n"; + echo "\n"; + echo '\n"; + + // TODO: try to make it so only non-team-members are listed + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "
' . _TEAM_CHOOSEMEMBER . "\n"; + + $query = 'SELECT mname as text, mnumber as value FROM '.sql_table('member'); + $template['name'] = 'memberid'; + $template['tabindex'] = 10000; + showlist($query,'select',$template); + + echo "
' . _TEAM_ADMIN; + help('teamadmin'); + echo "'; + $this->input_yesno('admin',0,10020); + echo "
' . _TEAM_ADD . "' . "
\n"; + + echo "
\n"; + echo "
\n"; + + $this->pagefoot(); + return; + } + + /** + * Add member to team + */ + function action_teamaddmember() { + global $member, $manager; + + $memberid = intPostVar('memberid'); + $blogid = intPostVar('blogid'); + $admin = intPostVar('admin'); + + // check if allowed + $member->blogAdminRights($blogid) or $this->disallow(); + + $blog =& $manager->getBlog($blogid); + if (!$blog->addTeamMember($memberid, $admin)) + $this->error(_ERROR_ALREADYONTEAM); + + $this->action_manageteam(); + + } + + /** + * @todo document this + */ + function action_teamdelete() { + global $member, $manager; + + $memberid = intRequestVar('memberid'); + $blogid = intRequestVar('blogid'); + + // check if allowed + $member->blogAdminRights($blogid) or $this->disallow(); + + $teammem =& $manager->getMember($memberid); + $blog =& $manager->getBlog($blogid); + + $this->pagehead(); + ?> +

+ +

getDisplayName()) ?>getName())) ?> +

+ + +
+ + addTicketHidden() ?> + + + +
+ pagefoot(); + } + + /** + * @todo document this + */ + function action_teamdeleteconfirm() { + global $member; + + $memberid = intRequestVar('memberid'); + $blogid = intRequestVar('blogid'); + + $error = $this->deleteOneTeamMember($blogid, $memberid); + if ($error) + $this->error($error); + + + $this->action_manageteam(); + } + + /** + * @todo document this + */ + function deleteOneTeamMember($blogid, $memberid) { + global $member, $manager; + + $blogid = intval($blogid); + $memberid = intval($memberid); + + // check if allowed + if (!$member->blogAdminRights($blogid)) + return _ERROR_DISALLOWED; + + // check if: - there remains at least one blog admin + // - (there remains at least one team member) + $tmem =& $manager->getMember($memberid); + + $manager->notify('PreDeleteTeamMember', array('member' => &$tmem, 'blogid' => $blogid)); + + if ($tmem->isBlogAdmin($blogid)) { + // check if there are more blog members left and at least one admin + // (check for at least two admins before deletion) + $query = 'SELECT * FROM '.sql_table('team') . ' WHERE tblog='.$blogid.' and tadmin=1'; + $r = DB::getResult($query); + if ($r->rowCount() < 2) + return _ERROR_ATLEASTONEBLOGADMIN; + } + + $query = 'DELETE FROM '.sql_table('team')." WHERE tblog=$blogid and tmember=$memberid"; + DB::execute($query); + + $manager->notify('PostDeleteTeamMember', array('member' => &$tmem, 'blogid' => $blogid)); + + return ''; + } + + /** + * @todo document this + */ + function action_teamchangeadmin() { + global $manager, $member; + + $blogid = intRequestVar('blogid'); + $memberid = intRequestVar('memberid'); + + // check if allowed + $member->blogAdminRights($blogid) or $this->disallow(); + + $mem =& $manager->getMember($memberid); + + // don't allow when there is only one admin at this moment + if ($mem->isBlogAdmin($blogid)) { + $r = DB::getResult('SELECT * FROM '.sql_table('team') . " WHERE tblog=$blogid and tadmin=1"); + if ($r->rowCount() == 1) + $this->error(_ERROR_ATLEASTONEBLOGADMIN); + } + + if ($mem->isBlogAdmin($blogid)) + $newval = 0; + else + $newval = 1; + + $query = 'UPDATE '.sql_table('team') ." SET tadmin=$newval WHERE tblog=$blogid and tmember=$memberid"; + DB::execute($query); + + // only show manageteam if member did not change its own admin privileges + if ($member->isBlogAdmin($blogid)) + $this->action_manageteam(); + else + $this->action_overview(_MSG_ADMINCHANGED); + } /** - * Admin::action_skinupdate() + * Admin::action_blogsettings() * * @param void * @return void */ - static private function action_skinupdate() + public function action_blogsettings() { - global $manager, $member; + global $member, $manager; - $skinid = intRequestVar('skinid'); - $content = trim(postVar('content')); - $type = postVar('type'); + $blogid = intRequestVar('blogid'); - $member->isAdmin() or self::disallow(); + // check if allowed + $member->blogAdminRights($blogid) or $this->disallow(); - $skin =& $manager->getSKIN($skinid); - $skin->update($type, $content); + $blog =& $manager->getBlog($blogid); - self::action_skinedittype(_SKIN_UPDATED); - return; - } - - /** - * Admin::action_skindelete() - * - * @param void - * @return void - */ - static private function action_skindelete() - { - global $CONF, $member; + $extrahead = "\n"; + $this->pagehead($extrahead); - $member->isAdmin() or self::disallow(); + echo '

(' . _BACKHOME . ")

\n"; + echo '

' . _EBLOG_TITLE . ": '{$this->bloglink($blog)}'

\n"; - $skinid = intRequestVar('skinid'); + echo '

' . _EBLOG_TEAM_TITLE . "

\n"; - // don't allow default skin to be deleted - if ( $skinid == $CONF['BaseSkin'] ) - { - self::error(_ERROR_DEFAULTSKIN); + echo '

' . _EBLOG_CURRENT_TEAM_MEMBER; + + $query = "SELECT mname, mrealname FROM %s, %s WHERE mnumber=tmember AND tblog=%d;"; + $query = sprintf($query, sql_table('member'), sql_table('team'), (integer) $blogid); + $res = DB::getResult($query); + $aMemberNames = array(); + foreach ( $res as $row ) + { + $aMemberNames[] = Entity::hsc($row['mname']) . ' (' . Entity::hsc($row['mrealname']). ')'; + } + echo implode(',', $aMemberNames); + + echo "

\n"; + echo '

'; + echo '' . _EBLOG_TEAM_TEXT . ''; + echo "

\n"; + + echo '

' . _EBLOG_SETTINGS_TITLE . "

\n"; + + echo "
\n"; + echo "
\n"; + + echo "\n"; + $manager->addTicketHidden() . "\n"; + echo "\n"; + + echo '' . "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + + // plugin options + $this->_insertPluginOptions('blog', $blogid); + + echo "\n"; + echo "
' . _EBLOG_CHANGE . "
' . _EBLOG_CHANGE . "' . "
' . _EBLOG_NAME . "' . "
' . _EBLOG_SHORTNAME; + help('shortblogname'); + echo _EBLOG_SHORTNAME_EXTRA; + echo "' . "
' . _EBLOG_DESC . "' . "
' . _EBLOG_URL . "' . "
' . _EBLOG_DEFSKIN; + help('blogdefaultskin'); + echo "\n"; + + $query = 'SELECT sdname as text, sdnumber as value FROM ' . sql_table('skin_desc'); + $template['name'] = 'defskin'; + $template['selected'] = $blog->getDefaultSkin(); + $template['tabindex'] = 50; + showlist($query, 'select', $template); + + echo "
' . _EBLOG_LINEBREAKS; + help('convertbreaks'); + echo "'; + $this->input_yesno('convertbreaks',$blog->convertBreaks(),55); + echo "
' . _EBLOG_ALLOWPASTPOSTING; + help('allowpastposting'); + echo "'; + $this->input_yesno('allowpastposting',$blog->allowPastPosting(),57); + echo "
' . _EBLOG_DISABLECOMMENTS; + echo "'; + $this->input_yesno('comments', $blog->commentsEnabled(), 60); + echo "
' . _EBLOG_ANONYMOUS . "'; + $this->input_yesno('public',$blog->isPublic(),70); + echo "
' . _EBLOG_REQUIREDEMAIL . "'; + $this->input_yesno('reqemail', $blog->emailRequired(),72); + echo "
' . _EBLOG_NOTIFY; + help('blognotify'); + echo "' . "
' . _EBLOG_NOTIFY_ON . "\n"; + + if ( !$blog->notifyOnComment() ) + { + echo "\n"; + } + else + { + echo "\n"; + } + echo '
\n"; + + if ( !$blog->notifyOnVote() ) + { + echo "\n"; + } + else + { + echo "\n"; + } + + echo '
\n"; + + if ( !$blog->notifyOnNewItem() ) + { + echo "\n"; + + } + else + { + echo "\n"; + } + + echo '\n"; + + echo "
' . _EBLOG_MAXCOMMENTS; + help('blogmaxcomments'); + echo "' . "
' . _EBLOG_UPDATE; + help('blogupdatefile'); + echo "' . "
' . _EBLOG_DEFCAT . "\n"; + $query = "SELECT cname as text, catid as value FROM %s WHERE cblog=%d;"; + $query = sprintf($query, sql_table('category'), (integer) $blog->getID()); + $template['name'] = 'defcat'; + $template['selected'] = $blog->getDefaultCategory(); + $template['tabindex'] = 110; + showlist($query, 'select', $template); + echo "
' . _EBLOG_OFFSET; + help('blogtimeoffset'); + echo "
\n"; + echo _EBLOG_STIME; + echo ' ' . i18n::formatted_datetime('%H:%M', time()) . '
'; + echo _EBLOG_BTIME; + echo '' . i18n::formatted_datetime('%H:%M', $blog->getCorrectTime()) . ''; + echo "
' . "
' . _EBLOG_SEARCH; + help('blogsearchable'); + echo "'; + $this->input_yesno('searchable', $blog->getSearchable(), 122); + echo "
\n"; + + echo "
\n"; + echo "
\n"; + + echo '

' . _EBLOG_CAT_TITLE . "

\n"; + + $query = 'SELECT * FROM '.sql_table('category').' WHERE cblog='.$blog->getID().' ORDER BY cname'; + $template['content'] = 'categorylist'; + $template['tabindex'] = 200; + + $manager->loadClass("ENCAPSULATE"); + $batch = new Batch('category'); + $batch->showlist($query,'table',$template); + + echo "
\n"; + echo "
\n"; + echo "\n"; + $manager->addTicketHidden() . "\n"; + echo "getID()}\" type=\"hidden\" />\n"; + + echo '' . "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "
' . _EBLOG_CAT_CREATE . "
' . _EBLOG_CAT_NAME . "
' . _EBLOG_CAT_DESC . "
' . _EBLOG_CAT_CREATE . "' . "
\n"; + echo "
\n"; + echo "
\n"; + + echo '

' . _PLUGINS_EXTRA . "

\n"; + $manager->notify('BlogSettingsFormExtras', array('blog' => &$blog)); + + $this->pagefoot(); + return; + } + + /** + * @todo document this + */ + function action_categorynew() { + global $member, $manager; + + $blogid = intRequestVar('blogid'); + + $member->blogAdminRights($blogid) or $this->disallow(); + + $cname = postVar('cname'); + $cdesc = postVar('cdesc'); + + if (!isValidCategoryName($cname)) + $this->error(_ERROR_BADCATEGORYNAME); + + $query = 'SELECT * FROM '.sql_table('category') . ' WHERE cname=' . DB::quoteValue($cname).' and cblog=' . intval($blogid); + $res = DB::getResult($query); + if ($res->rowCount() > 0) + $this->error(_ERROR_DUPCATEGORYNAME); + + $blog =& $manager->getBlog($blogid); + $newCatID = $blog->createNewCategory($cname, $cdesc); + + $this->action_blogsettings(); + } + + /** + * @todo document this + */ + function action_categoryedit($catid = '', $blogid = '', $desturl = '') { + global $member, $manager; + + if ($blogid == '') + $blogid = intGetVar('blogid'); + else + $blogid = intval($blogid); + if ($catid == '') + $catid = intGetVar('catid'); + else + $catid = intval($catid); + + $member->blogAdminRights($blogid) or $this->disallow(); + + $res = DB::getRow('SELECT * FROM '.sql_table('category')." WHERE cblog=$blogid AND catid=$catid"); + + $cname = $res['cname']; + $cdesc = $res['cdesc']; + + $extrahead = ''; + $this->pagehead($extrahead); + + echo "

(",_BACK_TO_BLOGSETTINGS,")

"; + + ?> +

''

+
+ + + + + addTicketHidden(); ?> + + + + + + + + + + + _insertPluginOptions('category',$catid); + ?> + + + + + +
+ +
+ pagefoot(); + } + + /** + * @todo document this + */ + function action_categoryupdate() { + global $member, $manager; + + $blogid = intPostVar('blogid'); + $catid = intPostVar('catid'); + $cname = postVar('cname'); + $cdesc = postVar('cdesc'); + $desturl = postVar('desturl'); + + $member->blogAdminRights($blogid) or $this->disallow(); + + if (!isValidCategoryName($cname)) + $this->error(_ERROR_BADCATEGORYNAME); + + $query = 'SELECT * FROM '.sql_table('category').' WHERE cname=' . DB::quoteValue($cname).' and cblog=' . intval($blogid) . " and not(catid=$catid)"; + $res = DB::getResult($query); + if ($res->rowCount() > 0) + $this->error(_ERROR_DUPCATEGORYNAME); + + $query = 'UPDATE '.sql_table('category').' SET' + . ' cname=' . DB::quoteValue($cname) . ',' + . ' cdesc=' . DB::quoteValue($cdesc) + . ' WHERE catid=' . $catid; + + DB::execute($query); + + // store plugin options + $aOptions = requestArray('plugoption'); + NucleusPlugin::apply_plugin_options($aOptions); + $manager->notify('PostPluginOptionsUpdate',array('context' => 'category', 'catid' => $catid)); + + + if ($desturl) { + redirect($desturl); + exit; + } else { + $this->action_blogsettings(); + } + } + + /** + * @todo document this + */ + function action_categorydelete() { + global $member, $manager; + + $blogid = intRequestVar('blogid'); + $catid = intRequestVar('catid'); + + $member->blogAdminRights($blogid) or $this->disallow(); + + $blog =& $manager->getBlog($blogid); + + // check if the category is valid + if (!$blog->isValidCategory($catid)) + $this->error(_ERROR_NOSUCHCATEGORY); + + // don't allow deletion of default category + if ($blog->getDefaultCategory() == $catid) + $this->error(_ERROR_DELETEDEFCATEGORY); + + // check if catid is the only category left for blogid + $query = 'SELECT catid FROM '.sql_table('category').' WHERE cblog=' . $blogid; + $res = DB::getResult($query); + if ($res->rowCount() == 1) + $this->error(_ERROR_DELETELASTCATEGORY); + + + $this->pagehead(); + ?> +

+ +
+ getCategoryName($catid)) ?> +
+ +
+ + addTicketHidden() ?> + + + +
+ pagefoot(); + } + + /** + * @todo document this + */ + function action_categorydeleteconfirm() { + global $member, $manager; + + $blogid = intRequestVar('blogid'); + $catid = intRequestVar('catid'); + + $member->blogAdminRights($blogid) or $this->disallow(); + + $error = $this->deleteOneCategory($catid); + if ($error) + $this->error($error); + + $this->action_blogsettings(); + } ++======= + + /** - * Admin::deleteOneCategory() - * Delete a category by its id ++ * Admin::action_skinedit() + * - * @param String $catid category id for deleting - * @return Void ++ * @param void ++ * @return void + */ - function deleteOneCategory($catid) ++ static private function action_skinedit() ++ { ++ global $member; ++ ++ $member->isAdmin() or self::disallow(); ++ ++ self::$skin->parse('skinedit'); ++ return; ++ } ++ ++ /** ++ * Admin::action_skineditgeneral() ++ * ++ * @param void ++ * @return void ++ */ ++ static private function action_skineditgeneral() ++ { ++ global $member; ++ ++ $skinid = intRequestVar('skinid'); ++ ++ $member->isAdmin() or self::disallow(); ++ ++ $error = self::skineditgeneral($skinid); ++ if ( $error ) ++ { ++ self::error($error); ++ return; ++ } ++ ++ self::action_skinedit(); ++ return; ++ } ++ ++ static private function action_skinedittype($msg = '') ++ { ++ global $member; ++ ++ $member->isAdmin() or self::disallow(); ++ ++ if ( $msg ) ++ { ++ self::$headMess = $msg; ++ } ++ ++ $type = requestVar('type'); ++ $type = trim($type); ++ $type = strtolower($type); ++ ++ if ( !isValidShortName($type) ) ++ { ++ self::error(_ERROR_SKIN_PARTS_SPECIAL_FORMAT); ++ return; ++ } ++ ++ self::$skin->parse('skinedittype'); ++ return; ++ } ++>>>>>>> skinnable-master ++ ++ /** ++ * Admin::action_skinupdate() ++ * ++ * @param void ++ * @return void ++ */ ++ static private function action_skinupdate() + { + global $manager, $member; + - $catid = intval($catid); - $blogid = getBlogIDFromCatID($catid); ++ $skinid = intRequestVar('skinid'); ++ $content = trim(postVar('content')); ++ $type = postVar('type'); + - if ( !$member->blogAdminRights($blogid) ) ++ $member->isAdmin() or self::disallow(); ++ ++ $skin =& $manager->getSKIN($skinid); ++ $skin->update($type, $content); ++ ++ self::action_skinedittype(_SKIN_UPDATED); ++ return; ++ } ++ ++ /** ++ * Admin::action_skindelete() ++ * ++ * @param void ++ * @return void ++ */ ++ static private function action_skindelete() ++ { ++ global $CONF, $member; ++ ++ $member->isAdmin() or self::disallow(); ++ ++ $skinid = intRequestVar('skinid'); ++ ++ // don't allow default skin to be deleted ++ if ( $skinid == $CONF['BaseSkin'] ) + { - return ERROR_DISALLOWED; ++ self::error(_ERROR_DEFAULTSKIN); + return; } - // get blog - $blog =& $manager->getBlog($blogid); + // don't allow deletion of default skins for blogs + $query = "SELECT bname FROM %s WHERE bdefskin=%d"; + $query = sprintf($query, sql_table('blog'), (integer) $skinid); - // check if the category is valid - if ( !$blog || !$blog->isValidCategory($catid) ) + $name = DB::getValue($query); + if ( $name ) { - return _ERROR_NOSUCHCATEGORY; + self::error(_ERROR_SKINDEFDELETE . Entity::hsc($name)); + return; } - $destcatid = $blog->getDefaultCategory(); + self::$skin->parse('skindelete'); + return; + } + + /** + * Admin::action_skindeleteconfirm() + * + * @param void + * @return void + */ + static private function action_skindeleteconfirm() + { + global $member, $CONF; - // don't allow deletion of default category - if ( $blog->getDefaultCategory() == $catid ) + $member->isAdmin() or self::disallow(); + + $skinid = intRequestVar('skinid'); + + // don't allow default skin to be deleted + if ( $skinid == $CONF['BaseSkin'] ) { - return _ERROR_DELETEDEFCATEGORY; + self::error(_ERROR_DEFAULTSKIN); + return; } ++<<<<<<< HEAD + // check if catid is the only category left for blogid + $query = 'SELECT catid FROM '.sql_table('category').' WHERE cblog=' . $blogid; + $res = DB::getResult($query); + if ( $res->rowCount() == 1 ) ++======= + // don't allow deletion of default skins for blogs + $query = "SELECT bname FROM %s WHERE bdefskin=%d;"; + $query = sprintf($query, sql_table('blog'), (integer) $skinid); + + $name = DB::getValue($query); + if ( $name ) + { + self::error(_ERROR_SKINDEFDELETE . Entity::hsc($name)); + return; + } + + self::skindeleteconfirm($skinid); + + self::action_skinoverview(); + return; + } + + /** + * Admin::action_skinremovetype() + * + * @param void + * @return void + */ + static private function action_skinremovetype() + { + global $member, $CONF; + + $member->isAdmin() or self::disallow(); + + $skinid = intRequestVar('skinid'); + $skintype = requestVar('type'); + + if ( !isValidShortName($skintype) ) ++>>>>>>> skinnable-master { - return _ERROR_DELETELASTCATEGORY; + self::error(_ERROR_SKIN_PARTS_SPECIAL_DELETE); + return; } - $manager->notify('PreDeleteCategory', array('catid' => $catid)); + self::$skin->parse('skinremovetype'); + return; + } + + /** + * Admin::action_skinremovetypeconfirm() + * + * @param void + * @return void + */ + static private function action_skinremovetypeconfirm() + { + global $member; ++<<<<<<< HEAD + // change category for all items to the default category + $query = 'UPDATE '.sql_table('item')." SET icat=$destcatid WHERE icat=$catid"; + DB::execute($query); ++======= + $member->isAdmin() or self::disallow(); ++>>>>>>> skinnable-master - // delete all associated plugin options - NucleusPlugin::delete_option_values('category', $catid); + $skinid = intRequestVar('skinid'); + $skintype = requestVar('type'); ++<<<<<<< HEAD + // delete category + $query = 'DELETE FROM '.sql_table('category').' WHERE catid=' .$catid; + DB::execute($query); ++======= + $error = self::skinremovetypeconfirm($skinid, $skintype); + if ( $error ) + { + self::error($error); + return; + } ++>>>>>>> skinnable-master - $manager->notify('PostDeleteCategory', array('catid' => $catid)); + self::action_skinedit(); return; } /** - * Admin::action_blogsettingsupdate - * Updating blog settings + * Admin::action_skinclone() * - * @param Void - * @return Void + * @param void + * @return void */ - function action_blogsettingsupdate() + static private function action_skinclone() { - global $member, $manager; + global $member; - $blogid = intRequestVar('blogid'); + $member->isAdmin() or self::disallow(); - $member->blogAdminRights($blogid) or $this->disallow(); + $skinid = intRequestVar('skinid'); - $blog =& $manager->getBlog($blogid); + self::skinclone($skinid); - $notify_address = trim(postVar('notify')); - $shortname = trim(postVar('shortname')); - $updatefile = trim(postVar('update')); + self::action_skinoverview(); + return; + } + + /** + * Admin::action_adminskinoverview() + * + * @param void + * @return void + */ + static private function action_adminskinoverview() + { + global $member; - $notifyComment = intPostVar('notifyComment'); - $notifyVote = intPostVar('notifyVote'); - $notifyNewItem = intPostVar('notifyNewItem'); + $member->isAdmin() or self::disallow(); - if ( $notifyComment == 0 ) + self::$skin->parse('adminskinoverview'); + return; + } + + /** + * Admin::action_adminskinnew() + * + * @param void + * @return void + */ + static private function action_adminskinnew() + { + global $member; + + $member->isAdmin() or self::disallow(); + + $name = trim(postVar('name')); + $desc = trim(postVar('desc')); + + if ( !isValidSkinName($name) ) { - $notifyComment = 1; + self::error(_ERROR_BADSKINNAME); + return; } - if ( $notifyVote == 0 ) + else if ( !preg_match('#^admin/#', $name) ) { - $notifyVote = 1; + self::error(_ERROR_BADADMINSKINNAME); + return; } - if ( $notifyNewItem == 0 ) + else if ( Skin::exists($name) ) { - $notifyNewItem = 1; + self::error(_ERROR_DUPSKINNAME); + return; } - $notifyType = $notifyComment * $notifyVote * $notifyNewItem; - if ( $notify_address && !NOTIFICATION::address_validation($notify_address) ) + Skin::createNew($name, $desc); + + self::action_adminskinoverview(); + return; + } + + /** + * Admin::action_adminskinedit() + * + * @param void + * @return void + */ + static private function action_adminskinedit() + { + global $member; + + $member->isAdmin() or self::disallow(); + + self::$skin->parse('adminskinedit'); + + return; + } + + /** + * Admin::action_adminskineditgeneral() + * + * @param void + * @return void + */ + static private function action_adminskineditgeneral() + { + global $member; + + $skinid = intRequestVar('skinid'); + + $member->isAdmin() or self::disallow(); + + $error = self::skineditgeneral($skinid, 'AdminActions'); + if ( $error ) { - $this->error(_ERROR_BADNOTIFY); + self::error($error); + return; } - if ( !isValidShortName($shortname) ) + self::action_adminskinedit(); + return; + } + + /** + * Admin::action_adminskinedittype() + * + * @param string $msg message for pageheader + * @return void + */ + static private function action_adminskinedittype($msg = '') + { + global $member; + + $member->isAdmin() or self::disallow(); + + if ( $msg ) { - $this->error(_ERROR_BADSHORTBLOGNAME); + self::$headMess = $msg; } + $type = requestVar('type'); + $type = trim($type); + $type = strtolower($type); - if ( ($blog->getShortName() != $shortname) && $manager->existsBlog($shortname) ) + if ( !isValidShortName($type) ) { - $this->error(_ERROR_DUPSHORTBLOGNAME); + self::error(_ERROR_SKIN_PARTS_SPECIAL_FORMAT); + return; } - // check if update file is writable - if ( $updatefile && !is_writeable($updatefile) ) + + self::$skin->parse('adminskinedittype'); + return; + } + + /** + * Admin::action_adminskinupdate() + * + * @param void + * @return void + */ + static private function action_adminskinupdate() + { + global $manager, $member; + + $skinid = intRequestVar('skinid'); + $content = trim(postVar('content')); + $type = postVar('type'); + + $member->isAdmin() or self::disallow(); + + $skin =& $manager->getSkin($skinid, 'AdminActions', 'AdminSkin'); + $skin->update($type, $content); + + self::action_adminskinedittype(_SKIN_UPDATED); + return; + } + + /** + * Admin::action_adminskindelete() + * + * @param void + * @return void + */ + static private function action_adminskindelete() + { + global $CONF, $member; + + $member->isAdmin() or self::disallow(); + + $skinid = intRequestVar('skinid'); + + // don't allow default skin to be deleted + if ( $skinid == $CONF['AdminSkin'] || $skinid == $CONF['BookmarkletSkin'] ) { - $this->error(_ERROR_UPDATEFILE); + self::error(_ERROR_DEFAULTSKIN); + return; } - $blog->setName(trim(postVar('name'))); - $blog->setShortName($shortname); - $blog->setNotifyAddress($notify_address); - $blog->setNotifyType($notifyType); - $blog->setMaxComments(postVar('maxcomments')); - $blog->setCommentsEnabled(postVar('comments')); - $blog->setTimeOffset(postVar('timeoffset')); - $blog->setUpdateFile($updatefile); - $blog->setURL(trim(postVar('url'))); - $blog->setDefaultSkin(intPostVar('defskin')); - $blog->setDescription(trim(postVar('desc'))); - $blog->setPublic(postVar('public')); - $blog->setConvertBreaks(intPostVar('convertbreaks')); - $blog->setAllowPastPosting(intPostVar('allowpastposting')); - $blog->setDefaultCategory(intPostVar('defcat')); - $blog->setSearchable(intPostVar('searchable')); - $blog->setEmailRequired(intPostVar('reqemail')); - $blog->writeSettings(); + /* don't allow if someone use it as a default*/ + $query = 'SELECT * FROM %s WHERE madminskin = %d or mbkmklt = %d;'; + $res = DB::getResult(sprintf($query, sql_table('member'), $skinid, $skinid)); - // store plugin options - $aOptions = requestArray('plugoption'); - NucleusPlugin::apply_plugin_options($aOptions); - $manager->notify('PostPluginOptionsUpdate',array('context' => 'blog', 'blogid' => $blogid, 'blog' => &$blog)); + $members = array(); + while ( $row = $res->fetch() ) { + $members[] = $row['mrealname']; + } + if ( count($members) ) + { + self::error(_ERROR_SKINDEFDELETE . implode(' ' . _AND . ' ', $members)); + return; + } + + self::$skin->parse('adminskindelete'); + return; + } + + /** + * Admin::action_adminskindeleteconfirm() + * + * @param void + * @return void + */ + static private function action_adminskindeleteconfirm() + { + global $member, $CONF; + + $member->isAdmin() or self::disallow(); + + $skinid = intRequestVar('skinid'); + + // don't allow default skin to be deleted + if ( $skinid == $CONF['AdminSkin'] || $skinid == $CONF['BookmarkletSkin'] ) + { + self::error(_ERROR_DEFAULTSKIN); + return; + } + + /* don't allow if someone use it as a default*/ + $query = 'SELECT * FROM %s WHERE madminskin = %d or mbkmklt = %d;'; + $res = DB::getResult(sprintf($query, sql_table('member'), $skinid, $skinid)); + + $members = array(); + while ( $row = $res->fetch() ) { + $members[] = $row['mrealname']; + } + if ( count($members) ) + { + self::error(_ERROR_SKINDEFDELETE . implode(' ' . _AND . ' ', $members)); + return; + } + + self::skindeleteconfirm($skinid); + + self::action_adminskinoverview(); + return; + } + + /** + * Admin::action_adminskinremovetype() + * + * @param void + * @return void + */ + static private function action_adminskinremovetype() + { + global $member, $CONF; + + $member->isAdmin() or self::disallow(); + + $skinid = intRequestVar('skinid'); + $skintype = requestVar('type'); - $this->action_overview(_MSG_SETTINGSCHANGED); + if ( !isValidShortName($skintype) ) + { + self::error(_ERROR_SKIN_PARTS_SPECIAL_DELETE); + return; + } + + self::$skin->parse('adminskinremovetype'); return; } ++<<<<<<< HEAD + + /** + * @todo document this + */ + function action_deleteblog() { + global $member, $CONF, $manager; + + $blogid = intRequestVar('blogid'); + + $member->blogAdminRights($blogid) or $this->disallow(); + + // check if blog is default blog + if ($CONF['DefaultBlog'] == $blogid) + $this->error(_ERROR_DELDEFBLOG); + + $blog =& $manager->getBlog($blogid); + + $this->pagehead(); + ?> +

+ +

+

+ +
+ getName()) ?> +
+ +
+ + addTicketHidden() ?> + + +
+ pagefoot(); + } ++======= ++>>>>>>> skinnable-master /** - * Admin::action_deleteblogconfirm() - * Delete Blog + * Admin::action_adminskinremovetypeconfirm() * - * @param Void - * @return Void + * @param void + * @return void */ - function action_deleteblogconfirm() + static private function action_adminskinremovetypeconfirm() { - global $member, $CONF, $manager; + global $member; - $blogid = intRequestVar('blogid'); - $manager->notify('PreDeleteBlog', array('blogid' => $blogid)); - $member->blogAdminRights($blogid) or $this->disallow(); + $member->isAdmin() or self::disallow(); - // check if blog is default blog - if ( $CONF['DefaultBlog'] == $blogid ) + $skinid = intRequestVar('skinid'); + $skintype = requestVar('type'); + + $error = self::skinremovetypeconfirm($skinid, $skintype); + if ( $error ) { - $this->error(_ERROR_DELDEFBLOG); + self::error($error); + return; } ++<<<<<<< HEAD + // delete all comments + $query = 'DELETE FROM '.sql_table('comment').' WHERE cblog='.$blogid; + DB::execute($query); + + // delete all items + $query = 'DELETE FROM '.sql_table('item').' WHERE iblog='.$blogid; + DB::execute($query); + + // delete all team members + $query = 'DELETE FROM '.sql_table('team').' WHERE tblog='.$blogid; + DB::execute($query); + + // delete all bans + $query = 'DELETE FROM '.sql_table('ban').' WHERE blogid='.$blogid; + DB::execute($query); + + // delete all categories + $query = 'DELETE FROM '.sql_table('category').' WHERE cblog='.$blogid; + DB::execute($query); ++======= + self::action_adminskinedit(); + return; + } + + /** + * Admin::action_adminskinclone() + * + * @param void + * @return void + */ + static private function action_adminskinclone() + { + global $member; - // delete all associated plugin options - NucleusPlugin::delete_option_values('blog', $blogid); + $member->isAdmin() or self::disallow(); + + $skinid = intRequestVar('skinid'); ++>>>>>>> skinnable-master + + self::skinclone($skinid, 'AdminActions'); ++<<<<<<< HEAD + // delete the blog itself + $query = 'DELETE FROM '.sql_table('blog').' WHERE bnumber='.$blogid; + DB::execute($query); ++======= + self::action_adminskinoverview(); + return; + } + + /** + * Admin::action_adminskinieoverview() + * + * @param void + * @return void + */ + static private function action_adminskinieoverview() + { + global $member; ++>>>>>>> skinnable-master - $manager->notify('PostDeleteBlog', array('blogid' => $blogid)); + $member->isAdmin() or self::disallow(); - $this->action_overview(_DELETED_BLOG); + self::$skin->parse('adminskinieoverview'); return; } ++<<<<<<< HEAD + + /** + * @todo document this + */ + function action_memberdelete() { + global $member, $manager; + + $memberid = intRequestVar('memberid'); + + ($member->getID() == $memberid) or $member->isAdmin() or $this->disallow(); + + $mem =& $manager->getMember($memberid); + + $this->pagehead(); + ?> +

+ +

getDisplayName()) ?> +

+ +

+ +

+ +
+ + addTicketHidden() ?> + + +
+ pagefoot(); + } + + /** + * @todo document this + */ + function action_memberdeleteconfirm() { + global $member; ++======= ++>>>>>>> skinnable-master - $memberid = intRequestVar('memberid'); - - ($member->getID() == $memberid) or $member->isAdmin() or $this->disallow(); - - $error = $this->deleteOneMember($memberid); - if ($error) - $this->error($error); - - if ($member->isAdmin()) - $this->action_usermanagement(); - else - $this->action_overview(_DELETED_MEMBER); - } - /** - * Admin::deleteOneMember() - * Delete a member by id + * Admin::action_adminskinieimport() * - * @static - * @params Integer $memberid member id - * @return String null string or error messages + * @param void + * @return void */ - function deleteOneMember($memberid) + static private function action_adminskinieimport() { - global $manager; + global $member; ++<<<<<<< HEAD + $memberid = intval($memberid); + $mem =& $manager->getMember($memberid); + + if ( !$mem->canBeDeleted() ) + { + return _ERROR_DELETEMEMBER; + } ++======= + $member->isAdmin() or self::disallow(); ++>>>>>>> skinnable-master - $manager->notify('PreDeleteMember', array('member' => &$mem)); + $skinFileRaw = postVar('skinfile'); + $mode = postVar('mode'); - /* unlink comments from memberid */ - if ( $memberid ) + $error = self::skinieimport($mode, $skinFileRaw); + if ( $error ) { - self::error($error); - return; ++<<<<<<< HEAD + $query = "UPDATE %s SET cmember=0, cuser=%s WHERE cmember=%d"; + $query = sprintf($query, sql_table('comment'), DB::quoteValue($mem->getDisplayName()), $memberid); + DB::execute($query); } - if ( !is_object(self::$skin) ) - { - self::action_adminskiniedoimport(); - } - else - { - self::$skin->parse('adminskinieimport'); - } - return; - } - - /** - * Admin::action_adminskiniedoimport() - * - * @param void - * @return void - */ - static private function action_adminskiniedoimport() - { - global $DIR_SKINS, $member, $CONF; + $query = 'DELETE FROM '.sql_table('member').' WHERE mnumber='.$memberid; + DB::execute($query); - $member->isAdmin() or self::disallow(); + $query = 'DELETE FROM '.sql_table('team').' WHERE tmember='.$memberid; + DB::execute($query); - $mode = postVar('mode'); - $skinFileRaw = postVar('skinfile'); - $allowOverwrite = intPostVar('overwrite'); + $query = 'DELETE FROM '.sql_table('activation').' WHERE vmember='.$memberid; + DB::execute($query); + + // delete all associated plugin options + NucleusPlugin::delete_option_values('member', $memberid); + + $manager->notify('PostDeleteMember', array('member' => &$mem)); + + return ''; + } + + /** + * @todo document this + */ + function action_createnewlog() { + global $member, $CONF, $manager; + + // Only Super-Admins can do this + $member->isAdmin() or $this->disallow(); + + $this->pagehead(); + + echo '

(',_BACKTOMANAGE,')

'; + ?> +

+ +

+ +

+ +

+ +
    +
  1. +
  2. +
+ +

+ +

+ +

+ +
+ + + addTicketHidden() ?> + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +
+
+ +
+ +
+ pagefoot(); + } + + /** + * @todo document this + */ + function action_addnewlog() { + global $member, $manager, $CONF; + + // Only Super-Admins can do this + $member->isAdmin() or $this->disallow(); + + $bname = trim(postVar('name')); + $bshortname = trim(postVar('shortname')); + $btimeoffset = postVar('timeoffset'); + $bdesc = trim(postVar('desc')); + $bdefskin = postVar('defskin'); + + if (!isValidShortName($bshortname)) + $this->error(_ERROR_BADSHORTBLOGNAME); + + if ($manager->existsBlog($bshortname)) + $this->error(_ERROR_DUPSHORTBLOGNAME); + + $manager->notify( + 'PreAddBlog', + array( + 'name' => &$bname, + 'shortname' => &$bshortname, + 'timeoffset' => &$btimeoffset, + 'description' => &$bdesc, + 'defaultskin' => &$bdefskin + ) + ); + + + // create blog + $query = sprintf('INSERT INTO %s (bname, bshortname, bdesc, btimeoffset, bdefskin) VALUES (%s, %s, %s, %s, %s)', + sql_table('blog'), + DB::quoteValue($bname), + DB::quoteValue($bshortname), + DB::quoteValue($bdesc), + DB::quoteValue($btimeoffset), + DB::quoteValue($bdefskin) + ); + DB::execute($query); + $blogid = DB::getInsertId(); + $blog =& $manager->getBlog($blogid); + + // create new category + $catdefname = (defined('_EBLOGDEFAULTCATEGORY_NAME') ? _EBLOGDEFAULTCATEGORY_NAME : 'General'); + $catdefdesc = (defined('_EBLOGDEFAULTCATEGORY_DESC') ? _EBLOGDEFAULTCATEGORY_DESC : 'Items that do not fit in other categories'); + $query = sprintf('INSERT INTO %s (cblog, cname, cdesc) VALUES (%d, %s, %s)', + sql_table('category'), + $blogid, + DB::quoteValue($catdefname), + DB::quoteValue($catdefdesc) + ); + DB::execute($query); + $catid = DB::getInsertId(); + + // set as default category + $blog->setDefaultCategory($catid); + $blog->writeSettings(); + + // create team member + $memberid = $member->getID(); + $query = sprintf('INSERT INTO %s (tmember, tblog, tadmin) VALUES (%d, %d, 1)', sql_table('team'), $memberid, $blogid); + DB::execute($query); + + $itemdeftitle = (defined('_EBLOG_FIRSTITEM_TITLE') ? _EBLOG_FIRSTITEM_TITLE : 'First Item'); + $itemdefbody = (defined('_EBLOG_FIRSTITEM_BODY') ? _EBLOG_FIRSTITEM_BODY : 'This is the first item in your weblog. Feel free to delete it.'); + + $blog->additem($blog->getDefaultCategory(),$itemdeftitle,$itemdefbody,'',$blogid, $memberid,$blog->getCorrectTime(),0,0,0); + + + $manager->notify( + 'PostAddBlog', + array( + 'blog' => &$blog + ) + ); + + $manager->notify( + 'PostAddCategory', + array( + 'blog' => &$blog, + 'name' => _EBLOGDEFAULTCATEGORY_NAME, + 'description' => _EBLOGDEFAULTCATEGORY_DESC, + 'catid' => $catid + ) + ); + + $this->pagehead(); + ?> +

+ +

+ +
    +
  1. +
  2. +
+ +

+ +

+
<?php
 +
 +$CONF['Self'] = '.php';
 +
 +include('./config.php');
 +
 +selectBlog('');
 +selector();
 +
 +?>
+ +

+ +

+ +
+ + addTicketHidden() ?> + + + + + + + +
+
+ +

+ +

+ +
+ + addTicketHidden() ?> + + + + + + + +
+
+ + pagefoot(); + + } + + /** + * @todo document this + */ + function action_addnewlog2() { + global $member, $manager; + + $member->blogAdminRights($blogid) or $this->disallow(); + + $burl = requestVar('url'); + $blogid = intRequestVar('blogid'); + + $blog =& $manager->getBlog($blogid); + $blog->setURL(trim($burl)); + $blog->writeSettings(); + + $this->action_overview(_MSG_NEWBLOG); + } + + /** + * @todo document this + */ + function action_skinieoverview() { + global $member, $DIR_LIBS, $manager; + + $member->isAdmin() or $this->disallow(); + + // load skinie class + include_once($DIR_LIBS . 'skinie.php'); + + $this->pagehead(); + + echo '

(',_BACKTOMANAGE,')

'; + + ?> +

+ +

+ 0) { + ?> +

+ + addTicketHidden() ?> + + + +
+ +

+ +

+ +

+ addTicketHidden() ?> + + + + + +

+ + +

+
+ + addTicketHidden() ?> + +

+ + + + + '; + echo ''; + echo ''; + echo ''; + } + + echo ''; + + // show list of templates + $res = DB::getResult('SELECT * FROM '.sql_table('template_desc')); + foreach ( $res as $row ) { + $id = 'templateexp' . $row['tdnumber']; + echo ''; + echo ''; + echo ''; + } + + ?> + + + + + + + +
',Entity::hsc($row['sddesc']),'
',_SKINIE_EXPORT_TEMPLATES,'
'; + echo '',Entity::hsc($row['tddesc']),'
+
+ + pagefoot(); + + } + + /** + * @todo document this + */ + function action_skinieimport() { + global $member, $DIR_LIBS, $DIR_SKINS, $manager; + + $member->isAdmin() or $this->disallow(); + + // load skinie class + include_once($DIR_LIBS . 'skinie.php'); + + $skinFileRaw= postVar('skinfile'); + $mode = postVar('mode'); + + $importer = new SkinImport(); + + // get full filename + if ($mode == 'file') + { + $skinFile = $DIR_SKINS . $skinFileRaw . '/skinbackup.xml'; + + // backwards compatibilty (in v2.0, exports were saved as skindata.xml) + if (!file_exists($skinFile)) + $skinFile = $DIR_SKINS . $skinFileRaw . '/skindata.xml'; + } else { + $skinFile = $skinFileRaw; + } + + // read only metadata + $error = $importer->readFile($skinFile, 1); + + // clashes + $skinNameClashes = $importer->checkSkinNameClashes(); + $templateNameClashes = $importer->checkTemplateNameClashes(); + $hasNameClashes = (count($skinNameClashes) > 0) || (count($templateNameClashes) > 0); + + if ($error) $this->error($error); + + $this->pagehead(); + + echo '

(',_BACK,')

'; + ?> +

+ + + +
+ + addTicketHidden() ?> + + + + +
+ + +
+ + + pagefoot(); + } + + /** + * @todo document this + */ + function action_skiniedoimport() { + global $member, $DIR_LIBS, $DIR_SKINS; + + $member->isAdmin() or $this->disallow(); + + // load skinie class + include_once($DIR_LIBS . 'skinie.php'); + + $skinFileRaw= postVar('skinfile'); + $mode = postVar('mode'); + + $allowOverwrite = intPostVar('overwrite'); + + // get full filename + if ($mode == 'file') + { + $skinFile = $DIR_SKINS . $skinFileRaw . '/skinbackup.xml'; + + // backwards compatibilty (in v2.0, exports were saved as skindata.xml) + if (!file_exists($skinFile)) + $skinFile = $DIR_SKINS . $skinFileRaw . '/skindata.xml'; + + } else { + $skinFile = $skinFileRaw; + } + + $importer = new SkinImport(); + + $error = $importer->readFile($skinFile); + + if ($error) + $this->error($error); + + $error = $importer->writeToDatabase($allowOverwrite); + + if ($error) + $this->error($error); + + $this->pagehead(); + + echo '

(',_BACKTOMANAGE,')

'; + ?> +

+ + + + pagefoot(); + + } + + /** + * @todo document this + */ + function action_skinieexport() { + global $member, $DIR_LIBS; + + $member->isAdmin() or $this->disallow(); + + // load skinie class + include_once($DIR_LIBS . 'skinie.php'); + + $aSkins = requestIntArray('skin'); + $aTemplates = requestIntArray('template'); + + if (!is_array($aTemplates)) $aTemplates = array(); + if (!is_array($aSkins)) $aSkins = array(); + + $skinList = array_keys($aSkins); + $templateList = array_keys($aTemplates); + + $info = postVar('info'); + + $exporter = new SkinExport(); + foreach ($skinList as $skinId) { + $exporter->addSkin($skinId); + } + foreach ($templateList as $templateId) { + $exporter->addTemplate($templateId); + } + $exporter->setInfo($info); + + $exporter->export(); + } + + /** + * @todo document this + */ + function action_templateoverview() { + global $member, $manager; + + $member->isAdmin() or $this->disallow(); + + $this->pagehead(); + + echo '

(',_BACKTOMANAGE,')

'; + + echo '

' . _TEMPLATE_TITLE . '

'; + echo '

' . _TEMPLATE_AVAILABLE_TITLE . '

'; + + $query = 'SELECT * FROM '.sql_table('template_desc').' ORDER BY tdname'; + $template['content'] = 'templatelist'; + $template['tabindex'] = 10; + showlist($query,'table',$template); + + echo '

' . _TEMPLATE_NEW_TITLE . '

'; + + ?> +
+ + + addTicketHidden() ?> + + + + + + + + + +
+ +
+ + pagefoot(); + } + + /** + * @todo document this + */ + function action_templateedit($msg = '') { + global $member, $manager; + + $templateid = intRequestVar('templateid'); + + $member->isAdmin() or $this->disallow(); + + $extrahead = ''; + $extrahead .= ''; + + $this->pagehead($extrahead); + + $templatename = Template::getNameFromId($templateid); + $templatedescription = Template::getDesc($templateid); + $template =& $manager->getTemplate($templatename); + + ?> +

+ () +

+ +

''

+ + "._MESSAGE.": $msg

"; + ?> + +

+ +
+
+ + + addTicketHidden() ?> + + + + + + + + + + + + + + + + + +_templateEditRow($template, _TEMPLATE_ITEMHEADER, 'ITEM_HEADER', '', 8); + $this->_templateEditRow($template, _TEMPLATE_ITEMBODY, 'ITEM', '', 9, 1); + $this->_templateEditRow($template, _TEMPLATE_ITEMFOOTER, 'ITEM_FOOTER', '', 10); + $this->_templateEditRow($template, _TEMPLATE_MORELINK, 'MORELINK', 'morelink', 20); + $this->_templateEditRow($template, _TEMPLATE_EDITLINK, 'EDITLINK', 'editlink', 25); + $this->_templateEditRow($template, _TEMPLATE_NEW, 'NEW', 'new', 30); +?> + + +_templateEditRow($template, _TEMPLATE_CHEADER, 'COMMENTS_HEADER', 'commentheaders', 40); + $this->_templateEditRow($template, _TEMPLATE_CBODY, 'COMMENTS_BODY', 'commentbody', 50, 1); + $this->_templateEditRow($template, _TEMPLATE_CFOOTER, 'COMMENTS_FOOTER', 'commentheaders', 60); + $this->_templateEditRow($template, _TEMPLATE_CONE, 'COMMENTS_ONE', 'commentwords', 70); + $this->_templateEditRow($template, _TEMPLATE_CMANY, 'COMMENTS_MANY', 'commentwords', 80); + $this->_templateEditRow($template, _TEMPLATE_CMORE, 'COMMENTS_CONTINUED', 'commentcontinued', 90); + $this->_templateEditRow($template, _TEMPLATE_CMEXTRA, 'COMMENTS_AUTH', 'memberextra', 100); +?> + + +_templateEditRow($template, _TEMPLATE_CNONE, 'COMMENTS_NONE', '', 110); +?> + + +_templateEditRow($template, _TEMPLATE_CTOOMUCH, 'COMMENTS_TOOMUCH', '', 120); +?> + + +_templateEditRow($template, _TEMPLATE_AHEADER, 'ARCHIVELIST_HEADER', '', 130); + $this->_templateEditRow($template, _TEMPLATE_AITEM, 'ARCHIVELIST_LISTITEM', '', 140); + $this->_templateEditRow($template, _TEMPLATE_AFOOTER, 'ARCHIVELIST_FOOTER', '', 150); +?> + + +_templateEditRow($template, _TEMPLATE_BLOGHEADER, 'BLOGLIST_HEADER', '', 160); + $this->_templateEditRow($template, _TEMPLATE_BLOGITEM, 'BLOGLIST_LISTITEM', '', 170); + $this->_templateEditRow($template, _TEMPLATE_BLOGFOOTER, 'BLOGLIST_FOOTER', '', 180); +?> + + +_templateEditRow($template, _TEMPLATE_CATHEADER, 'CATLIST_HEADER', '', 190); + $this->_templateEditRow($template, _TEMPLATE_CATITEM, 'CATLIST_LISTITEM', '', 200); + $this->_templateEditRow($template, _TEMPLATE_CATFOOTER, 'CATLIST_FOOTER', '', 210); +?> + + +_templateEditRow($template, _TEMPLATE_DHEADER, 'DATE_HEADER', 'dateheads', 220); + $this->_templateEditRow($template, _TEMPLATE_DFOOTER, 'DATE_FOOTER', 'dateheads', 230); + $this->_templateEditRow($template, _TEMPLATE_DFORMAT, 'FORMAT_DATE', 'datetime', 240); + $this->_templateEditRow($template, _TEMPLATE_TFORMAT, 'FORMAT_TIME', 'datetime', 250); + $this->_templateEditRow($template, _TEMPLATE_LOCALE, 'LOCALE', 'locale', 260); +?> + + +_templateEditRow($template, _TEMPLATE_PCODE, 'POPUP_CODE', '', 270); + $this->_templateEditRow($template, _TEMPLATE_ICODE, 'IMAGE_CODE', '', 280); + $this->_templateEditRow($template, _TEMPLATE_MCODE, 'MEDIA_CODE', '', 290); +?> + + +_templateEditRow($template, _TEMPLATE_SHIGHLIGHT, 'SEARCH_HIGHLIGHT', 'highlight',300); + $this->_templateEditRow($template, _TEMPLATE_SNOTFOUND, 'SEARCH_NOTHINGFOUND', 'nothingfound',310); +?> + + +notify('TemplateExtraFields',array('fields'=>&$pluginfields)); + + foreach ($pluginfields as $pfkey=>$pfvalue) { + echo "\n"; + echo '\n"; + foreach ($pfvalue as $pffield=>$pfdesc) { + $this->_templateEditRow($template, $pfdesc, $pffield, '',++$tab,0); + } + } +?> + + + + + +
+ + +
' . Entity::hen($pfkey) . "
+ + +
+ +
+
+ pagefoot(); + } + + /** + * @todo document this + */ + function _templateEditRow(&$template, $description, $name, $help = '', $tabindex = 0, $big = 0) { + static $count = 1; + if (!isset($template[$name])) $template[$name] = ''; + ?> + + + + isAdmin() or $this->disallow(); + + $name = postVar('tname'); + $desc = postVar('tdesc'); + + if (!isValidTemplateName($name)) + $this->error(_ERROR_BADTEMPLATENAME); + + if ((Template::getNameFromId($templateid) != $name) && Template::exists($name)) + $this->error(_ERROR_DUPTEMPLATENAME); + + + $name = DB::quoteValue($name); + $desc = DB::quoteValue($desc); + + // 1. Remove all template parts + $query = 'DELETE FROM '.sql_table('template').' WHERE tdesc=' . $templateid; + DB::execute($query); + + // 2. Update description + $query = 'UPDATE '.sql_table('template_desc').' SET' + . ' tdname=' . $name . ',' + . ' tddesc=' . $desc + . ' WHERE tdnumber=' . $templateid; + DB::execute($query); + + // 3. Add non-empty template parts + $this->addToTemplate($templateid, 'ITEM_HEADER', postVar('ITEM_HEADER')); + $this->addToTemplate($templateid, 'ITEM', postVar('ITEM')); + $this->addToTemplate($templateid, 'ITEM_FOOTER', postVar('ITEM_FOOTER')); + $this->addToTemplate($templateid, 'MORELINK', postVar('MORELINK')); + $this->addToTemplate($templateid, 'EDITLINK', postVar('EDITLINK')); + $this->addToTemplate($templateid, 'NEW', postVar('NEW')); + $this->addToTemplate($templateid, 'COMMENTS_HEADER', postVar('COMMENTS_HEADER')); + $this->addToTemplate($templateid, 'COMMENTS_BODY', postVar('COMMENTS_BODY')); + $this->addToTemplate($templateid, 'COMMENTS_FOOTER', postVar('COMMENTS_FOOTER')); + $this->addToTemplate($templateid, 'COMMENTS_CONTINUED', postVar('COMMENTS_CONTINUED')); + $this->addToTemplate($templateid, 'COMMENTS_TOOMUCH', postVar('COMMENTS_TOOMUCH')); + $this->addToTemplate($templateid, 'COMMENTS_AUTH', postVar('COMMENTS_AUTH')); + $this->addToTemplate($templateid, 'COMMENTS_ONE', postVar('COMMENTS_ONE')); + $this->addToTemplate($templateid, 'COMMENTS_MANY', postVar('COMMENTS_MANY')); + $this->addToTemplate($templateid, 'COMMENTS_NONE', postVar('COMMENTS_NONE')); + $this->addToTemplate($templateid, 'ARCHIVELIST_HEADER', postVar('ARCHIVELIST_HEADER')); + $this->addToTemplate($templateid, 'ARCHIVELIST_LISTITEM', postVar('ARCHIVELIST_LISTITEM')); + $this->addToTemplate($templateid, 'ARCHIVELIST_FOOTER', postVar('ARCHIVELIST_FOOTER')); + $this->addToTemplate($templateid, 'BLOGLIST_HEADER', postVar('BLOGLIST_HEADER')); + $this->addToTemplate($templateid, 'BLOGLIST_LISTITEM', postVar('BLOGLIST_LISTITEM')); + $this->addToTemplate($templateid, 'BLOGLIST_FOOTER', postVar('BLOGLIST_FOOTER')); + $this->addToTemplate($templateid, 'CATLIST_HEADER', postVar('CATLIST_HEADER')); + $this->addToTemplate($templateid, 'CATLIST_LISTITEM', postVar('CATLIST_LISTITEM')); + $this->addToTemplate($templateid, 'CATLIST_FOOTER', postVar('CATLIST_FOOTER')); + $this->addToTemplate($templateid, 'DATE_HEADER', postVar('DATE_HEADER')); + $this->addToTemplate($templateid, 'DATE_FOOTER', postVar('DATE_FOOTER')); + $this->addToTemplate($templateid, 'FORMAT_DATE', postVar('FORMAT_DATE')); + $this->addToTemplate($templateid, 'FORMAT_TIME', postVar('FORMAT_TIME')); + $this->addToTemplate($templateid, 'LOCALE', postVar('LOCALE')); + $this->addToTemplate($templateid, 'SEARCH_HIGHLIGHT', postVar('SEARCH_HIGHLIGHT')); + $this->addToTemplate($templateid, 'SEARCH_NOTHINGFOUND', postVar('SEARCH_NOTHINGFOUND')); + $this->addToTemplate($templateid, 'POPUP_CODE', postVar('POPUP_CODE')); + $this->addToTemplate($templateid, 'MEDIA_CODE', postVar('MEDIA_CODE')); + $this->addToTemplate($templateid, 'IMAGE_CODE', postVar('IMAGE_CODE')); + + $pluginfields = array(); + $manager->notify('TemplateExtraFields',array('fields'=>&$pluginfields)); + foreach ($pluginfields as $pfkey=>$pfvalue) { + foreach ($pfvalue as $pffield=>$pfdesc) { + $this->addToTemplate($templateid, $pffield, postVar($pffield)); + } + } + + // jump back to template edit + $this->action_templateedit(_TEMPLATE_UPDATED); + + } + ++======= ++ self::error($error); ++ return; ++ } ++ ++ if ( !is_object(self::$skin) ) ++ { ++ self::action_adminskiniedoimport(); ++ } ++ else ++ { ++ self::$skin->parse('adminskinieimport'); ++ } ++ return; ++ } ++ ++>>>>>>> skinnable-master + /** - * Admin::addToTemplate() - * - * @param Integer $id ID for template - * @param String $partname parts name - * @param String $content template contents - * @return Integer record index ++ * Admin::action_adminskiniedoimport() + * ++ * @param void ++ * @return void + */ - function addToTemplate($id, $partname, $content) ++ static private function action_adminskiniedoimport() + { - // don't add empty parts: - if ( !trim($content) ) ++ global $DIR_SKINS, $member, $CONF; ++ ++ $member->isAdmin() or self::disallow(); ++ ++ $mode = postVar('mode'); ++ $skinFileRaw = postVar('skinfile'); ++ $allowOverwrite = intPostVar('overwrite'); + + $error = self::skiniedoimport($mode, $skinFileRaw, $allowOverwrite); + if ( $error ) { - return -1; - self::error($error); - return; ++ self::error($error); ++ return; + } + ++<<<<<<< HEAD + $partname = DB::quoteValue($partname); + $content = DB::quoteValue($content); + + $query = "INSERT INTO %s (tdesc, tpartname, tcontent) VALUES (%d, %s, %s)"; + $query = sprintf($query, sql_table('template'), (integer) $id, $partname, $content); + if ( DB::execute($query) === FALSE ) + { + $err = DB::getError(); + exit(_ADMIN_SQLDIE_QUERYERROR . $err[2]); + } + return DB::getInsertId(); + } + + /** + * @todo document this + */ + function action_templatedelete() { + global $member, $manager; + + $member->isAdmin() or $this->disallow(); + + $templateid = intRequestVar('templateid'); + // TODO: check if template can be deleted + + $this->pagehead(); + + $name = Template::getNameFromId($templateid); + $desc = Template::getDesc($templateid); + + ?> +

+ +

+ () +

+ +
+ + addTicketHidden() ?> + + +
+ pagefoot(); + } + + /** + * @todo document this + */ + function action_templatedeleteconfirm() { + global $member, $manager; + + $templateid = intRequestVar('templateid'); + + $member->isAdmin() or $this->disallow(); + + $manager->notify('PreDeleteTemplate', array('templateid' => $templateid)); + + // 1. delete description + DB::execute('DELETE FROM '.sql_table('template_desc').' WHERE tdnumber=' . $templateid); + + // 2. delete parts + DB::execute('DELETE FROM '.sql_table('template').' WHERE tdesc=' . $templateid); + + $manager->notify('PostDeleteTemplate', array('templateid' => $templateid)); + + $this->action_templateoverview(); + } + + /** + * @todo document this + */ + function action_templatenew() { + global $member; + + $member->isAdmin() or $this->disallow(); + + $name = postVar('name'); + $desc = postVar('desc'); + + if (!isValidTemplateName($name)) + $this->error(_ERROR_BADTEMPLATENAME); + + if (Template::exists($name)) + $this->error(_ERROR_DUPTEMPLATENAME); + + $newTemplateId = Template::createNew($name, $desc); + + $this->action_templateoverview(); + } + + /** + * @todo document this + */ + function action_templateclone() { + global $member; + + $templateid = intRequestVar('templateid'); + + $member->isAdmin() or $this->disallow(); + + // 1. read old template + $name = Template::getNameFromId($templateid); + $desc = Template::getDesc($templateid); + + // 2. create desc thing + $name = "cloned" . $name; + + // if a template with that name already exists: + if (Template::exists($name)) { + $i = 1; + while (Template::exists($name . $i)) + $i++; + $name .= $i; + } + + $newid = Template::createNew($name, $desc); + + // 3. create clone + // go through parts of old template and add them to the new one + $res = DB::getResult('SELECT tpartname, tcontent FROM '.sql_table('template').' WHERE tdesc=' . $templateid); + foreach ( $res as $row ) { + $this->addToTemplate($newid, $row['tpartname'], $row['tcontent']); + } + + $this->action_templateoverview(); + } + + /** + * Admin::action_skinoverview() + * + * @param void + * @return void + */ + public function action_skinoverview() + { + global $member, $manager; + + $member->isAdmin() or $this->disallow(); + + $this->pagehead(); + + echo '

(' . _BACKTOMANAGE . ")

\n"; + echo '

' . _SKIN_EDIT_TITLE . "

\n"; + echo '

' . _SKIN_AVAILABLE_TITLE . "

\n"; + + $query = 'SELECT * FROM '.sql_table('skin_desc').' ORDER BY sdname;'; + $template['content'] = 'skinlist'; + $template['tabindex'] = 10; + + showlist($query,'table',$template); + + echo '

' . _SKIN_NEW_TITLE . "

\n"; + echo "
\n"; + echo "
\n"; + echo "\n"; + + $manager->addTicketHidden() . "\n"; + + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "
" . _SKIN_NAME; + echo help('shortnames'); + echo "
" . _SKIN_DESC . "
' . _SKIN_CREATE . "' . "
\n"; + + echo "
\n"; + echo "
\n"; + + $this->pagefoot(); + return; + } + + /** + * @todo document this + */ + function action_skinnew() { + global $member; + + $member->isAdmin() or $this->disallow(); + + $name = trim(postVar('name')); + $desc = trim(postVar('desc')); + + if (!isValidSkinName($name)) + $this->error(_ERROR_BADSKINNAME); + + if (Skin::exists($name)) + $this->error(_ERROR_DUPSKINNAME); + + $newId = Skin::createNew($name, $desc); + + $this->action_skinoverview(); + } + + /** + * Admin::action_skinedit() + * @param void + * @return void + */ + public function action_skinedit() + { + global $member, $manager; + + $skinid = intRequestVar('skinid'); + + $member->isAdmin() or $this->disallow(); + + $skin = new SKIN($skinid); + $default_skin_types = $skin->getDefaultTypes(); + $available_skin_types = $skin->getAvailableTypes(); + + $this->pagehead(); + + echo "

"; + echo '( ' . _SKIN_BACK . " )"; + echo "

\n"; + echo '

' . _SKIN_EDITONE_TITLE . $skin->getName() . "

\n"; + + echo '

' . _SKIN_PARTS_TITLE . "

\n"; + echo _SKIN_PARTS_MSG . "\n"; + echo "\n"; + + echo '

' . _SKIN_PARTS_SPECIAL . '

'; + echo "
\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "
\n"; + + /* NOTE: special skin parts has FALSE in its value */ + if ( in_array(FALSE, array_values($available_skin_types)) ) + { + $tabstart = 75; + + echo ''; + } + + echo '

' . _SKIN_GENSETTINGS_TITLE . "

\n"; + echo "
\n"; + echo "
\n"; + echo "\n"; + $manager->addTicketHidden() . "\n"; + echo "\n"; + + echo '' . "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "
'; + echo _SKIN_NAME; + help('shortnames'); + echo "' . "
' . _SKIN_DESC . "' . "
' . _SKIN_TYPE . "' . "
'; + echo _SKIN_INCLUDE_MODE; + help('includemode'); + echo "'; + $this->input_yesno('inc_mode', $skin->getIncludeMode(), 120, 'skindir', 'normal', _PARSER_INCMODE_SKINDIR, _PARSER_INCMODE_NORMAL); + echo "
'; + echo _SKIN_INCLUDE_PREFIX; + help('includeprefix'); + echo "' . "
' . _SKIN_CHANGE . "' . "
\n"; + + echo "
\n"; + echo "
\n"; + $this->pagefoot(); + return; + } + + /** + * @todo document this + */ + function action_skineditgeneral() { + global $member; + + $skinid = intRequestVar('skinid'); + + $member->isAdmin() or $this->disallow(); + + $name = postVar('name'); + $desc = postVar('desc'); + $type = postVar('type'); + $inc_mode = postVar('inc_mode'); + $inc_prefix = postVar('inc_prefix'); + + $skin = new SKIN($skinid); + + // 1. Some checks + if (!isValidSkinName($name)) + $this->error(_ERROR_BADSKINNAME); + + if (($skin->getName() != $name) && Skin::exists($name)) + $this->error(_ERROR_DUPSKINNAME); + + if (!$type) $type = 'text/html'; + if (!$inc_mode) $inc_mode = 'normal'; + + // 2. Update description + $skin->updateGeneralInfo($name, $desc, $type, $inc_mode, $inc_prefix); + + $this->action_skinedit(); + + } + + /** + * Admin::action_skinedittype() + * + * @param string $msg message for pageheader + * @return void + */ + public function action_skinedittype($msg = '') + { + global $member, $manager; + + $skinid = intRequestVar('skinid'); + $type = requestVar('type'); + + $member->isAdmin() or $this->disallow(); + + $type = trim($type); + $type = strtolower($type); + + if ( !isValidShortName($type) ) + { + $this->error(_ERROR_SKIN_PARTS_SPECIAL_FORMAT); + } + + $skin = new SKIN($skinid); + $skin_types = $skin->getAvailableTypes(); + if ( !array_key_exists($type, $skin_types) || !$skin_types[$type] ) + { + $friendlyName = ucfirst($type); + } + else + { + $friendlyName = $skin_types[$type]; + } + + $this->pagehead(); + + echo '

(' . _SKIN_GOBACK . ")

\n"; + + echo '

' . _SKIN_EDITPART_TITLE . " '" . Entity::hsc($skin->getName()) . "': " . Entity::hsc($friendlyName) . "

\n"; + + if ( $msg != '') + { + echo "

" . _MESSAGE . ": $msg

\n"; + } + + echo "
\n"; + echo "
\n"; + + echo "\n"; + $manager->addTicketHidden() . "\n"; + echo "\n"; + echo "\n"; + + echo '' . "\n"; + echo '' . "\n"; + echo '(skin type: ' . Entity::hsc($friendlyName) . ")\n"; + + if ( !array_key_exists($type, $skin_types) || !$skin_types[$type] ) + { + help('skinpartspecial'); + } + else + { + help('skinpart' . $type); + } + echo "
\n"; + + echo "\n"; + + echo "
\n"; + echo '' . "\n"; + echo '' . "\n"; + echo '(skin type: ' . Entity::hsc($friendlyName) . ")\n"; + + echo "
\n"; + echo "
\n"; + echo _SKIN_ALLOWEDVARS; + + $actions = $skin->getAllowedActionsForType($type); + + sort($actions); + + while ( $current = array_shift($actions) ) + { + // skip deprecated vars + if ( in_array($current, array('ifcat', 'imagetext', 'vars')) ) + { + continue; + } + + echo helplink("skinvar-{$current}") . "{$current}\n"; + + if ( count($actions) != 0 ) + { + echo ", "; + } + } + + echo "
\n"; + echo "
\n"; + echo _SKINEDIT_ALLOWEDBLOGS; + + $query = 'SELECT bshortname, bname FROM '.sql_table('blog'); + showlist($query, 'table', array('content'=>'shortblognames')); + + echo "
\n"; + echo _SKINEDIT_ALLOWEDTEMPLATESS; + + $query = 'SELECT tdname as name, tddesc as description FROM '.sql_table('template_desc'); + showlist($query, 'table', array('content'=>'shortnames')); + + echo "
\n"; + echo "
\n"; + + $this->pagefoot(); + + return; + } + + /** + * @todo document this + */ + function action_skinupdate() { + global $member; + + $skinid = intRequestVar('skinid'); + $content = trim(postVar('content')); + $type = postVar('type'); + + $member->isAdmin() or $this->disallow(); + + $skin = new SKIN($skinid); + $skin->update($type, $content); + + $this->action_skinedittype(_SKIN_UPDATED); + } + + /** + * @todo document this + */ + function action_skindelete() { + global $member, $manager, $CONF; + + $skinid = intRequestVar('skinid'); + + $member->isAdmin() or $this->disallow(); + + // don't allow default skin to be deleted + if ($skinid == $CONF['BaseSkin']) + $this->error(_ERROR_DEFAULTSKIN); + + // don't allow deletion of default skins for blogs + $query = 'SELECT bname FROM '.sql_table('blog').' WHERE bdefskin=' . $skinid; + $r = DB::getValue($query); + if ( $r ) + $this->error(_ERROR_SKINDEFDELETE . Entity::hsc($r)); + + $this->pagehead(); + + $skin = new SKIN($skinid); + $name = $skin->getName(); + $desc = $skin->getDescription(); + + ?> +

+ +

+ () +

+ +
+ + addTicketHidden() ?> + + +
+ pagefoot(); + } + + /** + * @todo document this + */ + function action_skindeleteconfirm() { + global $member, $CONF, $manager; + + $skinid = intRequestVar('skinid'); + + $member->isAdmin() or $this->disallow(); + + // don't allow default skin to be deleted + if ($skinid == $CONF['BaseSkin']) + $this->error(_ERROR_DEFAULTSKIN); + + // don't allow deletion of default skins for blogs + $query = 'SELECT bname FROM '.sql_table('blog').' WHERE bdefskin=' . $skinid; + $r = DB::getValue($query); + if ($r) + $this->error(_ERROR_SKINDEFDELETE .$r); + + $manager->notify('PreDeleteSkin', array('skinid' => $skinid)); + + // 1. delete description + DB::execute('DELETE FROM '.sql_table('skin_desc').' WHERE sdnumber=' . $skinid); + + // 2. delete parts + DB::execute('DELETE FROM '.sql_table('skin').' WHERE sdesc=' . $skinid); + + $manager->notify('PostDeleteSkin', array('skinid' => $skinid)); + + $this->action_skinoverview(); + } + + /** + * Admin::action_skinremovetype() + * + * @param void + * @return void + */ + public function action_skinremovetype() + { + global $member, $manager, $CONF; + + $skinid = intRequestVar('skinid'); + $skintype = requestVar('type'); + + if ( !isValidShortName($skintype) ) + { + $this->error(_ERROR_SKIN_PARTS_SPECIAL_DELETE); + } + + $member->isAdmin() or $this->disallow(); + + // don't allow default skinparts to be deleted + $skin = new Skin($skinid); + $default_skin_types = $skin->getDefaultTypes(); + if ( array_key_exists($skintype, $default_skin_types) ) + { + $this->error(_ERROR_SKIN_PARTS_SPECIAL_DELETE); + } + + $name = $skin->getName(); + $desc = $skin->getDescription(); + + $this->pagehead(); + + echo '

' . _DELETE_CONFIRM . "

\n"; + echo "

\n"; + echo _CONFIRMTXT_SKIN_PARTS_SPECIAL; + echo Entity::hsc($skintype); + echo '(' . Entity::hsc($name) . ')'; + echo ' (' . Entity::hsc($desc) . ')'; + echo "

\n"; + + echo "
\n"; + echo "
\n"; + echo "\n"; + $manager->addTicketHidden(); + echo "\n"; + echo '' . "\n"; + echo '' . "\n"; + echo "
\n"; + echo "
\n"; + $this->pagefoot(); + return; + } + + /** + * Admin::action_skinremovetypeconfirm() + * + * @param void + * @return void + */ + public function action_skinremovetypeconfirm() + { + global $member, $CONF, $manager; + + $skinid = intRequestVar('skinid'); + $skintype = requestVar('type'); + + if ( !isValidShortName($skintype) ) + { + $this->error(_ERROR_SKIN_PARTS_SPECIAL_DELETE); + } + + $member->isAdmin() or $this->disallow(); + + // don't allow default skinparts to be deleted + $skin = new Skin($skinid); + $default_skin_types = $skin->getDefaultTypes(); + if ( array_key_exists($skintype, $default_skin_types) ) + { + $this->error(_ERROR_SKIN_PARTS_SPECIAL_DELETE); } + $data = array( + 'skinid' => $skinid, + 'skintype' => $skintype + ); + $manager->notify('PreDeleteSkinPart', $data); + + // delete part + $query = "DELETE FROM %s WHERE sdesc=%d AND stype='%s';"; + $query = sprintf($query, sql_table('skin'), (integer) $skinid, $skintype); + DB::execute($query); + + $data = array( + 'skinid' => $skinid, + 'skintype' => $skintype + ); + $manager->notify('PostDeleteSkinPart', $data); + + $this->action_skinedit(); + return; + } + + /** + * @todo document this + */ + function action_skinclone() { + global $member; + + $skinid = intRequestVar('skinid'); + + $member->isAdmin() or $this->disallow(); + + // 1. read skin to clone + $skin = new SKIN($skinid); + + $name = "clone_" . $skin->getName(); + + // if a skin with that name already exists: + if (Skin::exists($name)) { + $i = 1; + while (Skin::exists($name . $i)) + $i++; + $name .= $i; + } + + // 2. create skin desc + $newid = Skin::createNew( + $name, + $skin->getDescription(), + $skin->getContentType(), + $skin->getIncludeMode(), + $skin->getIncludePrefix() + ); + + $query = "SELECT stype FROM " . sql_table('skin') . " WHERE sdesc = " . $skinid; + $res = DB::getResult($query); + foreach ( $res as $row) { + $this->skinclonetype($skin, $newid, $row['stype']); + } + + $this->action_skinoverview(); + + } ++======= + if ( !is_object(self::$skin) ) + { + global $DIR_SKINS; + $query = "SELECT min(sdnumber) FROM %s WHERE sdname != 'admin/bookmarklet' AND sdname LIKE 'admin/%%'"; + $query = sprintf($query, sql_table('skin_desc')); + $res = intval(DB::getValue($query)); + $query = "UPDATE %s SET value = %d WHERE name = 'AdminSkin'"; + $query = sprintf($query, sql_table('config'), $res); + DB::execute($query); + if ( $res ) + { + redirect($CONF['AdminURL']); + exit; + } + $skin = new Skin(0, 'AdminActions', 'AdminSkin'); + $skin->parse('importAdmin', $DIR_SKINS . 'admin/defaultimporter.skn'); + } + else + { + self::$skin->parse('adminskiniedoimport'); + } + return; + } ++>>>>>>> skinnable-master /** - * Admin::skinclonetype() + * Admin::action_adminskinieexport() * - * @param String $skin Skin object - * @param Integer $newid ID for this clone - * @param String $type type of skin - * @return Void + * @param void + * @return void */ - function skinclonetype($skin, $newid, $type) + static private function action_adminskinieexport() { ++<<<<<<< HEAD + $newid = intval($newid); + $content = $skin->getContentFromDB($type); + + if ( $content ) + { + $query = "INSERT INTO %s (sdesc, scontent, stype) VALUES (%d, '%s', '%s')"; + $query = sprintf($query, sql_table('skin'), (integer) $newid, $content, $type); + DB::execute($query); + } ++======= + global $member; + + $member->isAdmin() or self::disallow(); + + // load skinie class + $aSkins = requestIntArray('skin'); + $aTemplates = requestIntArray('template'); + $info = postVar('info'); + + self::skinieexport($aSkins, $aTemplates, $info); + ++>>>>>>> skinnable-master return; } @@@ -5097,337 -4253,14 +8864,346 @@@ * @param Void * @return Void */ - function action_settingsedit() { + static private function action_settingsedit() + { global $member, $manager, $CONF, $DIR_NUCLEUS, $DIR_MEDIA; ++<<<<<<< HEAD + + $member->isAdmin() or $this->disallow(); + + $this->pagehead(); + + echo '

(',_BACKTOMANAGE,')

'; + ?> + +

+ +
+
+ + + addTicketHidden() ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+ input_yesno('DisableSite',$CONF['DisableSite'],10060); ?> +
+ +
+
+ + input_yesno('DisableJsTools',$CONF['DisableJsTools'],10075); */ ?> + +
input_yesno('URLMode',$CONF['URLMode'],10077, + 'normal','pathinfo',_SETTINGS_URLMODE_NORMAL,_SETTINGS_URLMODE_PATHINFO); + + echo ' ', _SETTINGS_URLMODE_HELP; + + ?> + +
input_yesno('DebugVars',$CONF['DebugVars'],10078); + + ?> + +
+ + +
+ + + + +
+ + " . _WARNING_NOTADIR . ""; + if (!is_readable($DIR_MEDIA)) + echo "
" . _WARNING_NOTREADABLE . ""; + if (!is_writeable($DIR_MEDIA)) + echo "
" . _WARNING_NOTWRITABLE . ""; + ?> +
+ +
input_yesno('AllowUpload',$CONF['AllowUpload'],10090); ?>
+ +
+ +
input_yesno('MediaPrefix',$CONF['MediaPrefix'],10110); ?>
input_yesno('AllowLoginEdit',$CONF['AllowLoginEdit'],10120); ?>
+ + input_yesno('AllowMemberCreate',$CONF['AllowMemberCreate'],10130); ?> +
+
+
input_yesno('NewMemberCanLogon',$CONF['NewMemberCanLogon'],10140); ?> +
+ + input_yesno('AllowMemberMail',$CONF['AllowMemberMail'],10150); ?> +
+ + input_yesno('NonmemberMail',$CONF['NonmemberMail'],10155); ?> +
+ + input_yesno('ProtectMemNames',$CONF['ProtectMemNames'],10156); ?> +
input_yesno('CookieSecure',$CONF['CookieSecure'],10180); ?>
input_yesno('SessionCookie',$CONF['SessionCookie'],10190, + 1,0,_SETTINGS_COOKIESESSION,_SETTINGS_COOKIEMONTH); ?> +
input_yesno('LastVisit',$CONF['LastVisit'],10200); ?>
+ +
+
+ + ',_PLUGINS_EXTRA,''; + + $manager->notify( + 'GeneralSettingsFormExtras', + array() + ); + + $this->pagefoot(); ++======= + + $member->isAdmin() or self::disallow(); + + self::$skin->parse('settingsedit'); + return; ++>>>>>>> skinnable-master } /** @@@ -5437,61 -4270,65 +9213,65 @@@ * @param void * @return void */ - function action_settingsupdate() { + static private function action_settingsupdate() + { global $member, $CONF; - $member->isAdmin() or $this->disallow(); + $member->isAdmin() or self::disallow(); // check if email address for admin is valid if ( !NOTIFICATION::address_validation(postVar('AdminEmail')) ) { - $this->error(_ERROR_BADMAILADDRESS); + self::error(_ERROR_BADMAILADDRESS); + return; } // save settings - $this->updateConfig('DefaultBlog', postVar('DefaultBlog')); - $this->updateConfig('BaseSkin', postVar('BaseSkin')); - $this->updateConfig('IndexURL', postVar('IndexURL')); - $this->updateConfig('AdminURL', postVar('AdminURL')); - $this->updateConfig('PluginURL', postVar('PluginURL')); - $this->updateConfig('SkinsURL', postVar('SkinsURL')); - $this->updateConfig('ActionURL', postVar('ActionURL')); - $this->updateConfig('Locale', postVar('Locale')); - $this->updateConfig('AdminEmail', postVar('AdminEmail')); - $this->updateConfig('SessionCookie', postVar('SessionCookie')); - $this->updateConfig('AllowMemberCreate',postVar('AllowMemberCreate')); - $this->updateConfig('AllowMemberMail', postVar('AllowMemberMail')); - $this->updateConfig('NonmemberMail', postVar('NonmemberMail')); - $this->updateConfig('ProtectMemNames', postVar('ProtectMemNames')); - $this->updateConfig('SiteName', postVar('SiteName')); - $this->updateConfig('NewMemberCanLogon',postVar('NewMemberCanLogon')); - $this->updateConfig('DisableSite', postVar('DisableSite')); - $this->updateConfig('DisableSiteURL', postVar('DisableSiteURL')); - $this->updateConfig('LastVisit', postVar('LastVisit')); - $this->updateConfig('MediaURL', postVar('MediaURL')); - $this->updateConfig('AllowedTypes', postVar('AllowedTypes')); - $this->updateConfig('AllowUpload', postVar('AllowUpload')); - $this->updateConfig('MaxUploadSize', postVar('MaxUploadSize')); - $this->updateConfig('MediaPrefix', postVar('MediaPrefix')); - $this->updateConfig('AllowLoginEdit', postVar('AllowLoginEdit')); - $this->updateConfig('DisableJsTools', postVar('DisableJsTools')); - $this->updateConfig('CookieDomain', postVar('CookieDomain')); - $this->updateConfig('CookiePath', postVar('CookiePath')); - $this->updateConfig('CookieSecure', postVar('CookieSecure')); - $this->updateConfig('URLMode', postVar('URLMode')); - $this->updateConfig('CookiePrefix', postVar('CookiePrefix')); - $this->updateConfig('DebugVars', postVar('DebugVars')); - $this->updateConfig('DefaultListSize', postVar('DefaultListSize')); - $this->updateConfig('AdminCSS', postVar('AdminCSS')); - + self::updateConfig('DefaultBlog', postVar('DefaultBlog')); + self::updateConfig('BaseSkin', postVar('BaseSkin')); + self::updateConfig('IndexURL', postVar('IndexURL')); + self::updateConfig('AdminURL', postVar('AdminURL')); + self::updateConfig('PluginURL', postVar('PluginURL')); + self::updateConfig('SkinsURL', postVar('SkinsURL')); + self::updateConfig('ActionURL', postVar('ActionURL')); + self::updateConfig('Locale', postVar('Locale')); + self::updateConfig('AdminEmail', postVar('AdminEmail')); + self::updateConfig('SessionCookie', postVar('SessionCookie')); + self::updateConfig('AllowMemberCreate', postVar('AllowMemberCreate')); + self::updateConfig('AllowMemberMail', postVar('AllowMemberMail')); + self::updateConfig('NonmemberMail', postVar('NonmemberMail')); + self::updateConfig('ProtectMemNames', postVar('ProtectMemNames')); + self::updateConfig('SiteName', postVar('SiteName')); + self::updateConfig('NewMemberCanLogon', postVar('NewMemberCanLogon')); + self::updateConfig('DisableSite', postVar('DisableSite')); + self::updateConfig('DisableSiteURL', postVar('DisableSiteURL')); + self::updateConfig('LastVisit', postVar('LastVisit')); + self::updateConfig('MediaURL', postVar('MediaURL')); + self::updateConfig('AllowedTypes', postVar('AllowedTypes')); + self::updateConfig('AllowUpload', postVar('AllowUpload')); + self::updateConfig('MaxUploadSize', postVar('MaxUploadSize')); + self::updateConfig('MediaPrefix', postVar('MediaPrefix')); + self::updateConfig('AllowLoginEdit', postVar('AllowLoginEdit')); + self::updateConfig('DisableJsTools', postVar('DisableJsTools')); + self::updateConfig('CookieDomain', postVar('CookieDomain')); + self::updateConfig('CookiePath', postVar('CookiePath')); + self::updateConfig('CookieSecure', postVar('CookieSecure')); + self::updateConfig('URLMode', postVar('URLMode')); + self::updateConfig('CookiePrefix', postVar('CookiePrefix')); + self::updateConfig('DebugVars', postVar('DebugVars')); + self::updateConfig('DefaultListSize', postVar('DefaultListSize')); + self::updateConfig('AdminCSS', postVar('AdminCSS')); + self::updateConfig('AdminSkin', postVar('adminskin')); + self::updateConfig('BookmarkletSkin', postVar('bookmarklet')); + // load new config and redirect (this way, the new locale will be used is necessary) // note that when changing cookie settings, this redirect might cause the user // to have to log in again. getConfig(); redirect($CONF['AdminURL'] . '?action=manage'); - exit; + return; } - + /** * Admin::action_systemoverview() * Output system overview @@@ -5499,188 -4336,12 +9279,193 @@@ * @param void * @return void */ - function action_systemoverview() + static private function action_systemoverview() { ++<<<<<<< HEAD + global $member, $nucleus, $CONF; + + $this->pagehead(); + + echo '

' . _ADMIN_SYSTEMOVERVIEW_HEADING . "

\n"; + + if ( $member->isLoggedIn() && $member->isAdmin() ) + { + // Information about the used PHP and MySQL installation + echo '

' . _ADMIN_SYSTEMOVERVIEW_PHPANDMYSQL . "

\n\n"; + + // Version of PHP MySQL + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "
' . _ADMIN_SYSTEMOVERVIEW_VERSIONS . "
' . _ADMIN_SYSTEMOVERVIEW_PHPVERSION . "' . phpversion() . "
' . _ADMIN_SYSTEMOVERVIEW_MYSQLVERSION . "' . DB::getAttribute(PDO::ATTR_SERVER_VERSION) . ' (' . DB::getAttribute(PDO::ATTR_CLIENT_VERSION) . ')' . "
\n\n"; + + // Important PHP settings + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + $mqg = get_magic_quotes_gpc() ? 'On' : 'Off'; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + $mqr = get_magic_quotes_runtime() ? 'On' : 'Off'; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + $rg = ini_get('register_globals') ? 'On' : 'Off'; + echo '\n"; + echo "\n"; + echo "\n"; + echo "
' . _ADMIN_SYSTEMOVERVIEW_SETTINGS . "
magic_quotes_gpc' . "' . $mqg . "
magic_quotes_runtime' . "' . $mqr . "
register_globals' . "' . $rg . "
\n\n"; + + // Information about GD library + $gdinfo = gd_info(); + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + foreach ( $gdinfo as $key=>$value ) + { + if ( is_bool($value) ) + { + $value = $value ? _ADMIN_SYSTEMOVERVIEW_ENABLE : _ADMIN_SYSTEMOVERVIEW_DISABLE; + } + else + { + $value = Entity::hsc($value); + } + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + } + echo "\n"; + echo "
' . _ADMIN_SYSTEMOVERVIEW_GDLIBRALY . "
' . $key . "' . $value . "
\n\n"; + + // Check if special modules are loaded + ob_start(); + phpinfo(INFO_MODULES); + $im = ob_get_contents(); + ob_clean(); + echo '\n"; + echo "\n"; + echo ""; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + $modrewrite = (i18n::strpos($im, 'mod_rewrite') !== FALSE) ? + _ADMIN_SYSTEMOVERVIEW_ENABLE : + _ADMIN_SYSTEMOVERVIEW_DISABLE; + echo '\n"; + echo "\n"; + echo "\n"; + echo "
' . _ADMIN_SYSTEMOVERVIEW_MODULES . "
mod_rewrite' . "' . $modrewrite . "
\n\n"; + + // Information about the used Nucleus CMS + echo '

' . _ADMIN_SYSTEMOVERVIEW_NUCLEUSSYSTEM . "

\n"; + global $nucleus; + $nv = getNucleusVersion() / 100 . '(' . $nucleus['version'] . ')'; + $np = getNucleusPatchLevel(); + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "
Nucleus CMS' . "
' . _ADMIN_SYSTEMOVERVIEW_NUCLEUSVERSION . "' . $nv . "
' . _ADMIN_SYSTEMOVERVIEW_NUCLEUSPATCHLEVEL . "' . $np . "
\n\n"; + + // Important settings of the installation + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo '\n"; + $ohs = $CONF['alertOnHeadersSent'] ? + _ADMIN_SYSTEMOVERVIEW_ENABLE : + _ADMIN_SYSTEMOVERVIEW_DISABLE; + echo '\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo '\n"; + echo "\n"; + echo "\n"; + echo "
' . _ADMIN_SYSTEMOVERVIEW_NUCLEUSSETTINGS . "
' . '$CONF[' . "'Self']' . $CONF['Self'] . "
' . '$CONF[' . "'ItemURL']' . $CONF['ItemURL'] . "
' . '$CONF[' . "'alertOnHeadersSent']' . $ohs . "
i18n::get_current_charset()' . i18n::get_current_charset() . "
\n\n"; + + // Link to the online version test at the Nucleus CMS website + echo '

' . _ADMIN_SYSTEMOVERVIEW_VERSIONCHECK . "

\n"; + if ( $nucleus['codename'] != '') + { + $codenamestring = ' "' . $nucleus['codename'] . '"'; + } + else + { + $codenamestring = ''; + } + echo _ADMIN_SYSTEMOVERVIEW_VERSIONCHECK_TXT; + $checkURL = sprintf(_ADMIN_SYSTEMOVERVIEW_VERSIONCHECK_URL, getNucleusVersion(), getNucleusPatchLevel()); + echo ''; + echo 'Nucleus CMS ' . $nv . $codenamestring; + echo ''; + } + else + { + echo _ADMIN_SYSTEMOVERVIEW_NOT_ADMIN; + } + $this->pagefoot(); ++======= + self::$skin->parse('systemoverview'); + return; ++>>>>>>> skinnable-master } - + /** * Admin::updateConfig() * @@@ -5688,35 -4349,30 +9473,42 @@@ * @param string $val * @return integer return the ID in which the latest query posted */ - function updateConfig($name, $val) + static private function updateConfig($name, $val) { ++<<<<<<< HEAD + $name = DB::quoteValue($name); + $val = DB::quoteValue(trim($val)); + + $query = "UPDATE %s SET value=%s WHERE name=%s"; + $query = sprintf($query, sql_table('config'), $val, $name); + if ( DB::execute($query) === FALSE ) + { + $err = DB::getError(); + die("Query error: " . $err[2]); ++======= + $query = "UPDATE %s SET value=%s WHERE name=%s"; + $query = sprintf($query, sql_table('config'), DB::quoteValue($val), DB::quoteValue($name)); + if ( DB::execute($query) === FALSE ) + { + $err = DB::getError(); + die(_ADMIN_SQLDIE_QUERYERROR . $err[2]); ++>>>>>>> skinnable-master } return DB::getInsertId(); } /** + * Admin::error() * Error message - * @param string $msg message that will be shown + * + * @param string $msg message that will be shown + * @return void */ - function error($msg) + static public function error($msg) { - $this->pagehead(); - - echo "

Error!

\n"; - echo $msg; - echo "
\n"; - echo '' . _BACK . "\n"; - $this->pagefoot(); - exit; + self::$headMess = $msg; + self::$skin->parse('adminerrorpage'); + return; } /** @@@ -5726,637 -4382,276 +9518,713 @@@ * @param void * @return void */ - function disallow() + static public function disallow() { ActionLog::add(WARNING, _ACTIONLOG_DISALLOWED . serverVar('REQUEST_URI')); - $this->error(_ERROR_DISALLOWED); + self::error(_ERROR_DISALLOWED); + return; + } + + /** + * Admin::action_PluginAdmin() + * Output pluginadmin + * + * @param string $skinContents + * @param string $extrahead + * @return void + */ + static public function action_PluginAdmin($skinContents, $extrahead = '') + { + self::$extrahead .= $extrahead; + self::$skin->parse('pluginadmin', $skinContents); + return; } /** - * Admin::pagehead() - * Output admin page head + * Admin::action_bookmarklet() * * @param void * @return void */ ++<<<<<<< HEAD + function pagehead($extrahead = '') + { + global $member, $nucleus, $CONF, $manager; + + $manager->notify( + 'AdminPrePageHead', + array( + 'extrahead' => &$extrahead, + 'action' => $this->action)); + + $baseUrl = Entity::hsc($CONF['AdminURL']); + if ( !array_key_exists('AdminCSS',$CONF) ) + { + DB::execute("INSERT INTO ".sql_table('config')." VALUES ('AdminCSS', 'original')"); + $CONF['AdminCSS'] = 'original'; + } + + /* HTTP 1.1 application for no caching */ + header("Cache-Control: no-cache, must-revalidate"); + header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); + + $root_element = 'html'; + $charset = i18n::get_current_charset(); + $locale = preg_replace('#_#', '-', i18n::get_current_locale()); + + echo "xml_version_info}\" encoding=\"{$charset}\" ?>\n"; + echo "formal_public_identifier}\" \"{$this->system_identifier}\">\n"; + echo "<{$root_element} xmlns=\"{$this->xhtml_namespace}\" xml:lang=\"{$locale}\" lang=\"{$locale}\">\n"; + echo "\n"; + echo '' . Entity::hsc($CONF['SiteName']) . " - Admin\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "{$extrahead}\n"; + echo "\n\n"; + echo "\n"; + echo "
\n"; + echo "
\n"; + echo '

' . Entity::hsc($CONF['SiteName']) . "

\n"; + echo "
\n"; + echo "
\n"; + echo "
\n"; + echo "
\n"; + if ( $member->isLoggedIn() ) + { + echo _LOGGEDINAS . ' ' . $member->getDisplayName() ." - " . _LOGOUT. "
\n"; + echo "" . _ADMINHOME . " - "; + } + else + { + echo '' . _NOTLOGGEDIN . "
\n"; + } + echo ""._YOURSITE."
\n"; + echo '('; ++======= + static private function action_bookmarklet() + { + global $member, $manager; ++>>>>>>> skinnable-master - if (array_key_exists('codename', $nucleus) && $nucleus['codename'] != '' ) - { - $codenamestring = ' "' . $nucleus['codename'].'"'; - } - else - { - $codenamestring = ''; - } + $blogid = intRequestVar('blogid'); + $member->teamRights($blogid) or self::disallow(); - if ( $member->isLoggedIn() && $member->isAdmin() ) - { - $checkURL = sprintf(_ADMIN_SYSTEMOVERVIEW_VERSIONCHECK_URL, getNucleusVersion(), getNucleusPatchLevel()); - echo 'Nucleus CMS ' . $nucleus['version'] . $codenamestring . ''; - - $newestVersion = getLatestVersion(); - $newestCompare = str_replace('/','.',$newestVersion); - $currentVersion = str_replace(array('/','v'),array('.',''),$nucleus['version']); - if ( $newestVersion && version_compare($newestCompare, $currentVersion) > 0 ) - { - echo "
\n"; - echo ''; - echo _ADMIN_SYSTEMOVERVIEW_LATESTVERSION_TEXT . $newestVersion; - echo ""; - } - } - else - { - echo 'Nucleus CMS ' . $nucleus['version'] . $codenamestring; - } - echo ')'; - echo '
'; + self::$skin->parse('bookmarklet'); + return; + } + + /** + * Admin::action_actionlog() + * + * @param void + * @return void + */ + static private function action_actionlog() + { + global $member, $manager; + + $member->isAdmin() or self::disallow(); + + self::$skin->parse('actionlog'); return; } /** - * Admin::pagefoot() - * Output admin page foot include quickmenu + * Admin::action_banlist() * * @param void * @return void */ - function pagefoot() + static private function action_banlist() { - global $action, $member, $manager; + global $member, $manager; - $manager->notify( - 'AdminPrePageFoot', - array('action' => $this->action) - ); + $blogid = intRequestVar('blogid'); + $member->blogAdminRights($blogid) or self::disallow(); - if ( $member->isLoggedIn() && ($action != 'showlogin') ) - { - echo '

' . _LOGOUT . "

\n"; - echo "\n"; - } + self::$skin->parse('banlist'); + return; + } + + /** + * Admin::action_banlistdelete() + * + * @param void + * @return void + */ + static private function action_banlistdelete() + { + global $member, $manager; - echo "
\n"; - echo 'Nucleus CMS © 2002-' . date('Y') . ' ' . _ADMINPAGEFOOT_COPYRIGHT; - echo '-'; - echo '' . _ADMINPAGEFOOT_DONATE . "\n"; - echo "
\n"; + $blogid = intRequestVar('blogid'); + $member->blogAdminRights($blogid) or self::disallow(); + + self::$skin->parse('banlistdelete'); + return; + } + + /** + * Admin::action_banlistdeleteconfirm() + * + * @param void + * @return void + */ + static private function action_banlistdeleteconfirm() + { + global $member, $manager; - echo "\n"; - echo "
\n"; + $blogid = intPostVar('blogid'); + $allblogs = postVar('allblogs'); + $iprange = postVar('iprange'); - if ( ($action != 'showlogin') && ($member->isLoggedIn()) ) + $member->blogAdminRights($blogid) or self::disallow(); + + $deleted = array(); + + if ( !$allblogs ) { - echo "\n"; - - echo '

' . _QMENU_ADD . "

\n"; - echo "
\n"; - echo "

\n"; - echo "\n"; - - $showAll = requestVar('showall'); - - if ( ($member->isAdmin()) && ($showAll == 'yes') ) - { - // Super-Admins have access to all blogs! (no add item support though) - $query = 'SELECT bnumber as value, bname as text' - . ' FROM ' . sql_table('blog') - . ' ORDER BY bname'; - } - else + if ( Ban::removeBan($blogid, $iprange) ) { - $query = 'SELECT bnumber as value, bname as text' - . ' FROM ' . sql_table('blog') . ', ' . sql_table('team') - . ' WHERE tblog=bnumber and tmember=' . $member->getID() - . ' ORDER BY bname'; + $deleted[] = $blogid; } - $template['name'] = 'blogid'; - $template['tabindex'] = 15000; - $template['extra'] = _QMENU_ADD_SELECT; - $template['selected'] = -1; - $template['shorten'] = 10; - $template['shortenel'] = ''; - $template['javascript'] = 'onchange="return form.submit()"'; - showlist($query,'select',$template); - - echo "

\n"; - echo "
\n"; - - echo "

{$member->getDisplayName()}

\n"; - echo "\n"; - - // ---- general settings ---- - if ( $member->isAdmin() ) - { - echo '

' . _QMENU_MANAGE . "

\n"; - echo "\n"; - - echo "

" . _QMENU_LAYOUT . "

\n"; - echo "\n"; - } - - $aPluginExtras = array(); - $manager->notify( - 'QuickMenu', - array( - 'options' => &$aPluginExtras)); - - if ( count($aPluginExtras) > 0 ) + } + else + { + // get blogs fot which member has admin rights + $adminblogs = $member->getAdminBlogs(); + foreach ($adminblogs as $blogje) { - echo "

" . _QMENU_PLUGINS . "

\n"; - echo "\n"; } } - else if ( ($action == 'activate') || ($action == 'activatesetpwd') ) - { - echo '

' . _QMENU_ACTIVATE . '

' . _QMENU_ACTIVATE_TEXT; - } - else + if ( sizeof($deleted) == 0 ) { - // introduction text on login screen - echo '

' . _QMENU_INTRO . '

' . _QMENU_INTRO_TEXT; + self::error(_ERROR_DELETEBAN); + return; } - echo "\n"; - echo "
\n"; - - echo "\n"; - echo "
\n"; - - echo "\n"; - echo "
\n"; - - echo "\n"; - echo "
\n"; + /* TODO: we should use other ways */ + $_REQUEST['delblogs'] = $deleted; - echo "\n"; - echo "\n"; + self::$skin->parse('banlistdeleteconfirm'); return; } /** ++<<<<<<< HEAD + * Admin::action_bookmarklet() ++======= + * Admin::action_banlistnewfromitem() ++>>>>>>> skinnable-master * * @param void * @return void */ ++<<<<<<< HEAD + public function action_bookmarklet() + { + global $member, $manager; + + $blogid = intRequestVar('blogid'); + $member->teamRights($blogid) or $this->disallow(); + $blog =& $manager->getBlog($blogid); + + $this->pagehead(); + + echo '

(' . _BACKHOME . ")

\n"; + + echo '

' . _BOOKMARKLET_TITLE . "

\n"; + echo '

'; + echo _BOOKMARKLET_DESC1 . _BOOKMARKLET_DESC2 . _BOOKMARKLET_DESC3 . _BOOKMARKLET_DESC4 . _BOOKMARKLET_DESC5; + echo "

\n"; + + echo '

' . _BOOKMARKLET_BOOKARKLET . "

\n"; + echo '

'; + echo _BOOKMARKLET_BMARKTEXT . '' . _BOOKMARKLET_BMARKTEST . ''; + echo "

\n"; + echo '

'; + echo '' . sprintf(_BOOKMARKLET_ANCHOR, Entity::hsc($blog->getName())) . ''; + echo _BOOKMARKLET_BMARKFOLLOW; + echo "

\n"; + + $this->pagefoot(); + return; + } + + /** + * @todo document this + */ + function action_actionlog() { + global $member, $manager; + + $member->isAdmin() or $this->disallow(); + + $this->pagehead(); + + echo '

(',_BACKTOMANAGE,')

'; + + $url = $manager->addTicketToUrl('index.php?action=clearactionlog'); + + ?> +

+

+ ' . _ACTIONLOG_TITLE . ''; + + $query = 'SELECT * FROM '.sql_table('actionlog').' ORDER BY timestamp DESC'; + $template['content'] = 'actionlist'; + $amount = showlist($query,'table',$template); + + $this->pagefoot(); + + } + + /** + * @todo document this + */ + function action_banlist() { + global $member, $manager; + + $blogid = intRequestVar('blogid'); + + $member->blogAdminRights($blogid) or $this->disallow(); + + $blog =& $manager->getBlog($blogid); + + $this->pagehead(); + + echo '

(',_BACKHOME,')

'; + + echo '

' . _BAN_TITLE . " '". $this->bloglink($blog) ."'

"; + + $query = 'SELECT * FROM '.sql_table('ban').' WHERE blogid='.$blogid.' ORDER BY iprange'; + $template['content'] = 'banlist'; + $amount = showlist($query,'table',$template); + + if ($amount == 0) + echo _BAN_NONE; + + echo '

'._BAN_NEW_TITLE.'

'; + echo "

"._BAN_NEW_TEXT."

"; + + + $this->pagefoot(); + + } + + /** + * @todo document this + */ + function action_banlistdelete() { + global $member, $manager; + + $blogid = intRequestVar('blogid'); + $iprange = requestVar('iprange'); + + $member->blogAdminRights($blogid) or $this->disallow(); + + $blog =& $manager->getBlog($blogid); + $banBlogName = Entity::hsc($blog->getName()); + + $this->pagehead(); + ?> +

+ +
+ +

+ +

+ + +

+ +

+ +
+ + + +
+ +
+ +

+ +
+ addTicketHidden() ?> + + +
+ +
+ pagefoot(); + } + + /** + * @todo document this + */ + function action_banlistdeleteconfirm() { + global $member, $manager; + + $blogid = intPostVar('blogid'); + $allblogs = postVar('allblogs'); + $iprange = postVar('iprange'); + + $member->blogAdminRights($blogid) or $this->disallow(); + + $deleted = array(); + + if (!$allblogs) { + if (Ban::removeBan($blogid, $iprange)) + array_push($deleted, $blogid); + } else { + // get blogs fot which member has admin rights + $adminblogs = $member->getAdminBlogs(); + foreach ($adminblogs as $blogje) { + if (Ban::removeBan($blogje, $iprange)) + array_push($deleted, $blogje); + } + } + + if (sizeof($deleted) == 0) + $this->error(_ERROR_DELETEBAN); + + $this->pagehead(); + + echo '(',_BACK,')'; + echo '

'._BAN_REMOVED_TITLE.'

'; + echo "

"._BAN_REMOVED_TEXT."

"; + + echo ""; + + $this->pagefoot(); + + } + + /** + * @todo document this + */ + function action_banlistnewfromitem() { + $this->action_banlistnew(getBlogIDFromItemID(intRequestVar('itemid'))); + } + + /** + * @todo document this + */ + function action_banlistnew($blogid = '') { + global $member, $manager; + + if ($blogid == '') + $blogid = intRequestVar('blogid'); + + $ip = requestVar('ip'); + + $member->blogAdminRights($blogid) or $this->disallow(); + + $blog =& $manager->getBlog($blogid); + + $this->pagehead(); + ?> +

+ + +
+ +

+ +

+ +
+ + +
+ +
+ + + +
+ + + + "; + echo ""; + } + ?> +
+ +

+ +

+ +
+ + +
+ +
+ +

+ +

+ +
+ +

+ +
+ + addTicketHidden() ?> + +
+ +
+ + pagefoot(); + } + + /** + * @todo document this + */ + function action_banlistadd() { + global $member; + + $blogid = intPostVar('blogid'); + $allblogs = postVar('allblogs'); + $iprange = postVar('iprange'); + if ($iprange == "custom") + $iprange = postVar('customiprange'); + $reason = postVar('reason'); + + $member->blogAdminRights($blogid) or $this->disallow(); + + // TODO: check IP range validity + + if (!$allblogs) { + if (!Ban::addBan($blogid, $iprange, $reason)) + $this->error(_ERROR_ADDBAN); + } else { + // get blogs fot which member has admin rights + $adminblogs = $member->getAdminBlogs(); + $failed = 0; + foreach ($adminblogs as $blogje) { + if (!Ban::addBan($blogje, $iprange, $reason)) + $failed = 1; + } + if ($failed) + $this->error(_ERROR_ADDBAN); + } + + $this->action_banlist(); + + } + + /** + * @todo document this + */ + function action_clearactionlog() { + global $member; + + $member->isAdmin() or $this->disallow(); + + ActionLog::clear(); + + $this->action_manage(_MSG_ACTIONLOGCLEARED); + } + + /** + * @todo document this + */ + function action_backupoverview() { + global $member, $manager; + + $member->isAdmin() or $this->disallow(); + + $this->pagehead(); + + echo '

(',_BACKTOMANAGE,')

'; + ?> +

+ +

+ +

+ +

+ + addTicketHidden() ?> + + +
+ +

+ + +

+ +
+ + +

+ +
+ +

+ +

+ + addTicketHidden() ?> + +

+ +
+
+

++======= + static private function action_banlistnewfromitem() + { + global $manager; + + $itemid = intRequestVar('itemid'); + $item =& $manager->getItem($itemid, 1, 1); + self::action_banlistnew($item['blogid']); + return; + } + + /** + * Admin::action_banlistnew() + * + * @param integer $blogid ID for weblog + * @return void + */ + static private function action_banlistnew($blogid = '') + { + global $member, $manager; + + if ( $blogid == '' ) + { + $blogid = intRequestVar('blogid'); + } + + $ip = requestVar('ip'); + + $member->blogAdminRights($blogid) or self::disallow(); + + /* TODO: we should consider to use the other way instead of this */ + $_REQUEST['blogid'] = $blogid; + + self::$skin->parse('banlistnew'); + + return; + } ++>>>>>>> skinnable-master - pagefoot(); - } + /** + * Admin::action_banlistadd() + * + * @param void + * @return void + */ + static private function action_banlistadd() + { + global $member; + + $blogid = intPostVar('blogid'); + $allblogs = postVar('allblogs'); + $iprange = postVar('iprange'); + + if ( $iprange == "custom" ) + { + $iprange = postVar('customiprange'); + } + $reason = postVar('reason'); + + $member->blogAdminRights($blogid) or self::disallow(); + + // TODO: check IP range validity + + if ( !$allblogs ) + { + if ( !Ban::addBan($blogid, $iprange, $reason) ) + { + self::error(_ERROR_ADDBAN); + return; + } + } + else + { + // get blogs fot which member has admin rights + $adminblogs = $member->getAdminBlogs(); + $failed = 0; + foreach ($adminblogs as $blogje) + { + if ( !Ban::addBan($blogje, $iprange, $reason) ) + { + $failed = 1; + } + } + if ( $failed ) + { + self::error(_ERROR_ADDBAN); + return; + } + } + self::action_banlist(); + return; + } + + /** + * Admin::action_clearactionlog() + * + * @param void + * @return void + */ + static private function action_clearactionlog() + { + global $member; + + $member->isAdmin() or self::disallow(); + + ActionLog::clear(); + + self::action_manage(_MSG_ACTIONLOGCLEARED); + return; + } + + /** + * Admin::action_backupoverview() + * + * @param void + * @return void + */ + static private function action_backupoverview() + { + global $member, $manager; + + $member->isAdmin() or self::disallow(); + + self::$skin->parse('backupoverview'); + return; + } /** * Admin::action_backupcreate() @@@ -6366,11 -4661,11 +10234,11 @@@ * @return void * */ - function action_backupcreate() + static private function action_backupcreate() { global $member, $DIR_LIBS; - $member->isAdmin() or $this->disallow(); + $member->isAdmin() or self::disallow(); // use compression ? $useGzip = (integer) postVar('gzip'); @@@ -6382,7 -4677,7 +10250,7 @@@ @set_time_limit(1200); Backup::do_backup($useGzip); - exit; + return; } /** @@@ -6392,15 -4687,16 +10260,16 @@@ * @param void * @return void */ - function action_backuprestore() + static private function action_backuprestore() { global $member, $DIR_LIBS; - $member->isAdmin() or $this->disallow(); + $member->isAdmin() or self::disallow(); if ( intPostVar('letsgo') != 1 ) { - $this->error(_ERROR_BACKUP_NOTSURE); + self::error(_ERROR_BACKUP_NOTSURE); + return; } include($DIR_LIBS . 'backup.php'); @@@ -6412,11 -4708,10 +10281,10 @@@ $message = Backup::do_restore(); if ( $message != '' ) { - $this->error($message); + self::error($message); + return; } - $this->pagehead(); - echo '

' . _RESTORE_COMPLETE . "

\n"; - $this->pagefoot(); + self::$skin->parse('backuprestore'); return; } @@@ -6428,128 -4723,42 +10296,101 @@@ * @return void * */ - function action_pluginlist() + static private function action_pluginlist() { global $DIR_PLUGINS, $member, $manager; // check if allowed - $member->isAdmin() or $this->disallow(); + $member->isAdmin() or self::disallow(); - $this->pagehead(); - - echo '

(',_BACKTOMANAGE,')

'; - - echo '

' , _PLUGS_TITLE_MANAGE , ' ', help('plugins'), '

'; - - echo '

' , _PLUGS_TITLE_INSTALLED , '   ', helplink('getplugins'), _PLUGS_TITLE_GETPLUGINS, '

'; - - $query = 'SELECT * FROM '.sql_table('plugin').' ORDER BY porder ASC'; - - $template['content'] = 'pluginlist'; - $template['tabindex'] = 10; - showlist($query, 'table', $template); - - echo '

' . _PLUGS_TITLE_UPDATE . "

\n"; - echo '

' . _PLUGS_TEXT_UPDATE . "

\n"; - echo '
' . "\n"; - echo "
\n"; - echo '' . "\n"; - $manager->addTicketHidden(); - echo '' . "\n"; - echo "
\n"; - echo "
\n"; - - echo '

' . _PLUGS_TITLE_NEW . "

\n"; - - // find a list of possibly non-installed plugins - $candidates = array(); - $dirhandle = opendir($DIR_PLUGINS); + self::$skin->parse('pluginlist'); + return; + } + + /** + * Admin::action_pluginhelp() + * + * @param void + * @return void + */ + static private function action_pluginhelp() + { + global $member, $manager, $DIR_PLUGINS, $CONF; ++<<<<<<< HEAD + while ( $filename = readdir($dirhandle) ) + { + if ( preg_match('#^NP_(.*)\.php$#', $filename, $matches) ) + { + $name = $matches[1]; + + // only show in list when not yet installed + $query = 'SELECT * FROM %s WHERE pfile = %s'; + $query = sprintf($query, sql_table('plugin'), DB::quoteValue('NP_'.$name)); + $res = DB::getResult($query); + + if ( $res->rowCount() == 0 ) + { + array_push($candidates, $name); + } + } + } ++======= + // check if allowed + $member->isAdmin() or self::disallow(); ++>>>>>>> skinnable-master - closedir($dirhandle); + $plugid = intGetVar('plugid'); - if ( sizeof($candidates) > 0 ) - { - echo '

' . _PLUGS_ADD_TEXT . "

\n"; - - echo '
' . "\n"; - echo "
\n"; - echo '' . "\n"; - $manager->addTicketHidden(); - echo '\n"; - echo '\n"; - echo "
\n"; - echo "
\n"; - } - else + if ( !$manager->pidInstalled($plugid) ) { - echo '

', _PLUGS_NOCANDIDATES, '

'; + self::error(_ERROR_NOSUCHPLUGIN); + return; } - $this->pagefoot(); + self::$skin->parse('pluginhelp'); return; } ++<<<<<<< HEAD + /** + * @todo document this + */ + function action_pluginhelp() { + global $member, $manager, $DIR_PLUGINS, $CONF; + + // check if allowed + $member->isAdmin() or $this->disallow(); + + $plugid = intGetVar('plugid'); + + if (!$manager->pidInstalled($plugid)) + $this->error(_ERROR_NOSUCHPLUGIN); + + $plugName = $manager->getPluginNameFromPid($plugid); + + $this->pagehead(); + + echo '

(',_PLUGS_BACK,')

'; + + echo '

',_PLUGS_HELP_TITLE,': ',Entity::hsc($plugName),'

'; + + $plug =& $manager->getPlugin($plugName); + $helpFile = $DIR_PLUGINS.$plug->getShortName().'/help.html'; + + if (($plug->supportsFeature('HelpPage') > 0) && (@file_exists($helpFile))) { + @readfile($helpFile); + } else { + echo '

Error: ', _ERROR_PLUGNOHELPFILE,'

'; + echo '

(',_BACK,')

'; + } + + + $this->pagefoot(); + } + ++======= ++>>>>>>> skinnable-master /** * Admin::action_pluginadd() * @@@ -6557,325 -4766,358 +10398,590 @@@ * @return Void * */ - function action_pluginadd() + static private function action_pluginadd() { global $member, $manager, $DIR_PLUGINS; // check if allowed - $member->isAdmin() or $this->disallow(); + $member->isAdmin() or self::disallow(); + + $name = postVar('filename'); + + if ( $manager->pluginInstalled($name) ) + { + self::error(_ERROR_DUPPLUGIN); + return; + } + + if ( !checkPlugin($name) ) + { + self::error(_ERROR_PLUGFILEERROR . ' (' . Entity::hsc($name) . ')'); + return; + } + + // get number of currently installed plugins ++<<<<<<< HEAD ++ $res = DB::getResult('SELECT * FROM '.sql_table('plugin')); ++======= + $res = DB::getResult('SELECT * FROM ' . sql_table('plugin')); ++>>>>>>> skinnable-master + $numCurrent = $res->rowCount(); + + // plugin will be added as last one in the list + $newOrder = $numCurrent + 1; + + $data = array('file' => &$name); + $manager->notify('PreAddPlugin', $data); + + // do this before calling getPlugin (in case the plugin id is used there) ++<<<<<<< HEAD ++ $query = 'INSERT INTO '.sql_table('plugin').' (porder, pfile) VALUES ('.$newOrder.','.DB::quoteValue($name).')'; ++======= + $query = "INSERT INTO %s (porder, pfile) VALUES (%d, %s);"; + $query = sprintf($query, sql_table('plugin'), (integer) $newOrder, DB::quoteValue($name)); ++>>>>>>> skinnable-master + DB::execute($query); + $iPid = DB::getInsertId(); + + $manager->clearCachedInfo('installedPlugins'); + + // Load the plugin for condition checking and instalation + $plugin =& $manager->getPlugin($name); + + // check if it got loaded (could have failed) + if ( !$plugin ) + { ++<<<<<<< HEAD ++ DB::execute('DELETE FROM ' . sql_table('plugin') . ' WHERE pid='. intval($iPid)); ++======= + $query = "DELETE FROM %s WHERE pid=%d;"; + $query = sprintf($query, sql_table('plugin'), (integer) $iPid); + + DB::execute($query); + ++>>>>>>> skinnable-master + $manager->clearCachedInfo('installedPlugins'); + self::error(_ERROR_PLUGIN_LOAD); + return; + } + + // check if plugin needs a newer Nucleus version + if ( getNucleusVersion() < $plugin->getMinNucleusVersion() ) + { + // uninstall plugin again... + self::deleteOnePlugin($plugin->getID()); + + // ...and show error + self::error(_ERROR_NUCLEUSVERSIONREQ . Entity::hsc($plugin->getMinNucleusVersion())); + return; + } + + // check if plugin needs a newer Nucleus version + if ( (getNucleusVersion() == $plugin->getMinNucleusVersion()) && (getNucleusPatchLevel() < $plugin->getMinNucleusPatchLevel()) ) + { + // uninstall plugin again... + self::deleteOnePlugin($plugin->getID()); + + // ...and show error + self::error(_ERROR_NUCLEUSVERSIONREQ . Entity::hsc( $plugin->getMinNucleusVersion() . ' patch ' . $plugin->getMinNucleusPatchLevel() ) ); + return; + } + + $pluginList = $plugin->getPluginDep(); + foreach ( $pluginList as $pluginName ) + { + $res = DB::getResult('SELECT * FROM '.sql_table('plugin') . ' WHERE pfile=' . DB::quoteValue($pluginName)); + if ($res->rowCount() == 0) + { + // uninstall plugin again... + self::deleteOnePlugin($plugin->getID()); + self::error(sprintf(_ERROR_INSREQPLUGIN, Entity::hsc($pluginName))); + return; + } + } + + // call the install method of the plugin + $plugin->install(); + + $data = array('plugin' => &$plugin); + $manager->notify('PostAddPlugin', $data); + + // update all events + self::action_pluginupdate(); + return; + } + + /** + * ADMIN:action_pluginupdate(): + * + * @param Void + * @return Void + * + */ + static private function action_pluginupdate() + { + global $member, $manager, $CONF; + + // check if allowed + $member->isAdmin() or self::disallow(); + + // delete everything from plugin_events + DB::execute('DELETE FROM '.sql_table('plugin_event')); + + // loop over all installed plugins + $res = DB::getResult('SELECT pid, pfile FROM '.sql_table('plugin')); + foreach ( $res as $row ) + { + $pid = $row['pid']; + $plug =& $manager->getPlugin($row['pfile']); + if ( $plug ) + { + $eventList = $plug->getEventList(); + foreach ( $eventList as $eventName ) + { + $query = "INSERT INTO %s (pid, event) VALUES (%d, %s)"; + $query = sprintf($query, sql_table('plugin_event'), (integer) $pid, DB::quoteValue($eventName)); + DB::execute($query); + } + } + } + redirect($CONF['AdminURL'] . '?action=pluginlist'); + return; + } + + /** + * Admin::action_plugindelete() + * + * @param void + * @return void + */ + static private function action_plugindelete() + { + global $member, $manager; + + // check if allowed + $member->isAdmin() or self::disallow(); + + $pid = intGetVar('plugid'); + + if ( !$manager->pidInstalled($pid) ) + { + self::error(_ERROR_NOSUCHPLUGIN); + return; + } + + self::$skin->parse('plugindelete'); + return; + } + + /** + * Admin::action_plugindeleteconfirm() + * + * @param void + * @return void + */ + static private function action_plugindeleteconfirm() + { + global $member, $manager, $CONF; + + // check if allowed + $member->isAdmin() or self::disallow(); + + $pid = intPostVar('plugid'); + + $error = self::deleteOnePlugin($pid, 1); + if ( $error ) + { + self::error($error); + return; + } + + redirect($CONF['AdminURL'] . '?action=pluginlist'); + return; + } + + /** + * Admin::deleteOnePlugin() + * + * @param integer $pid + * @param boolean $callUninstall + * @return string empty or message if failed + */ + static public function deleteOnePlugin($pid, $callUninstall = 0) + { + global $manager; - $name = postVar('filename'); + $pid = intval($pid); - if ( $manager->pluginInstalled($name) ) + if ( !$manager->pidInstalled($pid) ) { - $this->error(_ERROR_DUPPLUGIN); + return _ERROR_NOSUCHPLUGIN; } - if ( !checkPlugin($name) ) + $query = "SELECT pfile as result FROM %s WHERE pid=%d;"; + $query = sprintf($query, sql_table('plugin'), (integer) $pid); + $name = DB::getValue($query); + + // check dependency before delete + $res = DB::getResult('SELECT pfile FROM ' . sql_table('plugin')); + foreach ( $res as $row ) { - $this->error(_ERROR_PLUGFILEERROR . ' (' . Entity::hsc($name) . ')'); + $plug =& $manager->getPlugin($row['pfile']); + if ( $plug ) + { + $depList = $plug->getPluginDep(); + foreach ( $depList as $depName ) + { + if ( $name == $depName ) + { + return sprintf(_ERROR_DELREQPLUGIN, $row['pfile']); + } + } + } } - // get number of currently installed plugins - $res = DB::getResult('SELECT * FROM '.sql_table('plugin')); - $numCurrent = $res->rowCount(); - - // plugin will be added as last one in the list - $newOrder = $numCurrent + 1; - - $manager->notify( - 'PreAddPlugin', - array( - 'file' => &$name - ) - ); - - // do this before calling getPlugin (in case the plugin id is used there) - $query = 'INSERT INTO '.sql_table('plugin').' (porder, pfile) VALUES ('.$newOrder.','.DB::quoteValue($name).')'; - DB::execute($query); - $iPid = DB::getInsertId(); - - $manager->clearCachedInfo('installedPlugins'); - - // Load the plugin for condition checking and instalation - $plugin =& $manager->getPlugin($name); + $data = array('plugid' => $pid); + $manager->notify('PreDeletePlugin', $data); - // check if it got loaded (could have failed) - if ( !$plugin ) + // call the unInstall method of the plugin + if ( $callUninstall ) { - DB::execute('DELETE FROM ' . sql_table('plugin') . ' WHERE pid='. intval($iPid)); - $manager->clearCachedInfo('installedPlugins'); - $this->error(_ERROR_PLUGIN_LOAD); + $plugin =& $manager->getPlugin($name); + if ( $plugin ) + { + $plugin->unInstall(); + } } - // check if plugin needs a newer Nucleus version - if ( getNucleusVersion() < $plugin->getMinNucleusVersion() ) + // delete all subscriptions + DB::execute('DELETE FROM ' . sql_table('plugin_event') . ' WHERE pid=' . $pid); + + // delete all options + // get OIDs from plugin_option_desc + $res = DB::getResult('SELECT oid FROM ' . sql_table('plugin_option_desc') . ' WHERE opid=' . $pid); + $aOIDs = array(); + foreach ( $res as $row ) { - // uninstall plugin again... - $this->deleteOnePlugin($plugin->getID()); - - // ...and show error - $this->error(_ERROR_NUCLEUSVERSIONREQ . Entity::hsc($plugin->getMinNucleusVersion())); + array_push($aOIDs, $row['oid']); } - // check if plugin needs a newer Nucleus version - if ( (getNucleusVersion() == $plugin->getMinNucleusVersion()) && (getNucleusPatchLevel() < $plugin->getMinNucleusPatchLevel()) ) + // delete from plugin_option and plugin_option_desc + DB::execute('DELETE FROM ' . sql_table('plugin_option_desc') . ' WHERE opid=' . $pid); + if (count($aOIDs) > 0) { - // uninstall plugin again... - $this->deleteOnePlugin($plugin->getID()); - - // ...and show error - $this->error(_ERROR_NUCLEUSVERSIONREQ . Entity::hsc( $plugin->getMinNucleusVersion() . ' patch ' . $plugin->getMinNucleusPatchLevel() ) ); + DB::execute('DELETE FROM ' . sql_table('plugin_option') . ' WHERE oid in (' . implode(',', $aOIDs) . ')'); } - $pluginList = $plugin->getPluginDep(); - foreach ( $pluginList as $pluginName ) + // update order numbers + $res = DB::getValue('SELECT porder FROM ' . sql_table('plugin') . ' WHERE pid=' . $pid); + DB::execute('UPDATE ' . sql_table('plugin') . ' SET porder=(porder - 1) WHERE porder>' . $res); + + // delete row + DB::execute('DELETE FROM ' . sql_table('plugin') . ' WHERE pid=' . $pid); + + $manager->clearCachedInfo('installedPlugins'); + $data = array('plugid' => $pid); + $manager->notify('PostDeletePlugin', $data); + + return ''; + } + + /** + * Admin::action_pluginup() + * + * @param void + * @return void + */ + static private function action_pluginup() + { + global $member, $manager, $CONF; + + // check if allowed + $member->isAdmin() or self::disallow(); + + $plugid = intGetVar('plugid'); + + if ( !$manager->pidInstalled($plugid) ) { ++<<<<<<< HEAD + $res = DB::getResult('SELECT * FROM '.sql_table('plugin') . ' WHERE pfile=' . DB::quoteValue($pluginName)); + if ($res->rowCount() == 0) + { + // uninstall plugin again... + $this->deleteOnePlugin($plugin->getID()); + $this->error(sprintf(_ERROR_INSREQPLUGIN, Entity::hsc($pluginName))); + } ++======= + self::error(_ERROR_NOSUCHPLUGIN); + return; ++>>>>>>> skinnable-master } - // call the install method of the plugin - $plugin->install(); + // 1. get old order number + $oldOrder = DB::getValue('SELECT porder FROM ' . sql_table('plugin') . ' WHERE pid=' . $plugid); - $manager->notify( - 'PostAddPlugin', - array( - 'plugin' => &$plugin - ) - ); + // 2. calculate new order number + $newOrder = ($oldOrder > 1) ? ($oldOrder - 1) : 1; - // update all events - $this->action_pluginupdate(); + // 3. update plug numbers + DB::execute('UPDATE ' . sql_table('plugin') . ' SET porder=' . $oldOrder . ' WHERE porder=' . $newOrder); + DB::execute('UPDATE ' . sql_table('plugin') . ' SET porder=' . $newOrder . ' WHERE pid=' . $plugid); + + //self::action_pluginlist(); + // To avoid showing ticket in the URL, redirect to pluginlist, instead. + redirect($CONF['AdminURL'] . '?action=pluginlist'); return; } /** - * ADMIN:action_pluginupdate(): - * - * @param Void - * @return Void + * Admin::action_plugindown() * + * @param void + * @return void */ - function action_pluginupdate() + static private function action_plugindown() { global $member, $manager, $CONF; // check if allowed ++<<<<<<< HEAD + $member->isAdmin() or $this->disallow(); + + // delete everything from plugin_events + DB::execute('DELETE FROM '.sql_table('plugin_event')); + + // loop over all installed plugins + $res = DB::getResult('SELECT pid, pfile FROM '.sql_table('plugin')); + foreach ( $res as $row ) + { + $pid = $row['pid']; + $plug =& $manager->getPlugin($row['pfile']); + if ( $plug ) + { + $eventList = $plug->getEventList(); + foreach ( $eventList as $eventName ) + { + $query = "INSERT INTO %s (pid, event) VALUES (%d, %s)"; + $query = sprintf($query, sql_table('plugin_event'), (integer) $pid, DB::quoteValue($eventName)); + DB::execute($query); + } + } ++======= + $member->isAdmin() or self::disallow(); + + $plugid = intGetVar('plugid'); + if ( !$manager->pidInstalled($plugid) ) + { + self::error(_ERROR_NOSUCHPLUGIN); + return; ++>>>>>>> skinnable-master } + + // 1. get old order number + $oldOrder = DB::getValue('SELECT porder FROM ' . sql_table('plugin') . ' WHERE pid=' . $plugid); + + $res = DB::getResult('SELECT * FROM ' . sql_table('plugin')); + $maxOrder = $res->rowCount(); + + // 2. calculate new order number + $newOrder = ($oldOrder < $maxOrder) ? ($oldOrder + 1) : $maxOrder; + + // 3. update plug numbers + DB::execute('UPDATE ' . sql_table('plugin') . ' SET porder=' . $oldOrder . ' WHERE porder=' . $newOrder); + DB::execute('UPDATE ' . sql_table('plugin') . ' SET porder=' . $newOrder . ' WHERE pid=' . $plugid); + + //self::action_pluginlist(); + // To avoid showing ticket in the URL, redirect to pluginlist, instead. redirect($CONF['AdminURL'] . '?action=pluginlist'); return; } ++<<<<<<< HEAD + /** + * @todo document this + */ + function action_plugindelete() { + global $member, $manager; + + // check if allowed + $member->isAdmin() or $this->disallow(); + + $pid = intGetVar('plugid'); + + if (!$manager->pidInstalled($pid)) + $this->error(_ERROR_NOSUCHPLUGIN); + + $this->pagehead(); + ?> +

+ +

getPluginNameFromPid($pid) ?>?

+ +
+ addTicketHidden() ?> + + + +
+ pagefoot(); + } + + /** + * @todo document this + */ + function action_plugindeleteconfirm() { + global $member, $manager, $CONF; + + // check if allowed + $member->isAdmin() or $this->disallow(); + + $pid = intPostVar('plugid'); + + $error = $this->deleteOnePlugin($pid, 1); + if ($error) { + $this->error($error); + } + + redirect($CONF['AdminURL'] . '?action=pluginlist'); +// $this->action_pluginlist(); + } + + /** + * @todo document this + */ + function deleteOnePlugin($pid, $callUninstall = 0) { + global $manager; + + $pid = intval($pid); + + if (!$manager->pidInstalled($pid)) + return _ERROR_NOSUCHPLUGIN; + + $name = DB::getValue('SELECT pfile as result FROM '.sql_table('plugin').' WHERE pid='.$pid); + +/* // call the unInstall method of the plugin + if ($callUninstall) { + $plugin =& $manager->getPlugin($name); + if ($plugin) $plugin->unInstall(); + }*/ + + // check dependency before delete + $res = DB::getResult('SELECT pfile FROM '.sql_table('plugin')); + foreach ( $res as $row ) { + $plug =& $manager->getPlugin($row['pfile']); + if ($plug) + { + $depList = $plug->getPluginDep(); + foreach ($depList as $depName) + { + if ($name == $depName) + { + return sprintf(_ERROR_DELREQPLUGIN, $row['pfile']); + } + } + } + } + + $manager->notify('PreDeletePlugin', array('plugid' => $pid)); + + // call the unInstall method of the plugin + if ($callUninstall) { + $plugin =& $manager->getPlugin($name); + if ($plugin) $plugin->unInstall(); + } + + // delete all subscriptions + DB::execute('DELETE FROM '.sql_table('plugin_event').' WHERE pid=' . $pid); + + // delete all options + // get OIDs from plugin_option_desc + $res = DB::getResult('SELECT oid FROM ' . sql_table('plugin_option_desc') . ' WHERE opid=' . $pid); + $aOIDs = array(); + foreach ( $res as $row ) { + array_push($aOIDs, $row['oid']); + } + + // delete from plugin_option and plugin_option_desc + DB::execute('DELETE FROM '.sql_table('plugin_option_desc').' WHERE opid=' . $pid); + if (count($aOIDs) > 0) + DB::execute('DELETE FROM '.sql_table('plugin_option').' WHERE oid in ('.implode(',',$aOIDs).')'); + + // update order numbers + $res = DB::getValue('SELECT porder FROM '.sql_table('plugin').' WHERE pid=' . $pid); + DB::execute('UPDATE '.sql_table('plugin').' SET porder=(porder - 1) WHERE porder>'.$res); + + // delete row + DB::execute('DELETE FROM '.sql_table('plugin').' WHERE pid='.$pid); + + $manager->clearCachedInfo('installedPlugins'); + $manager->notify('PostDeletePlugin', array('plugid' => $pid)); + + return ''; + } + + /** + * @todo document this + */ + function action_pluginup() { + global $member, $manager, $CONF; + + // check if allowed + $member->isAdmin() or $this->disallow(); + + $plugid = intGetVar('plugid'); + + if (!$manager->pidInstalled($plugid)) + $this->error(_ERROR_NOSUCHPLUGIN); + + // 1. get old order number + $oldOrder = DB::getValue('SELECT porder FROM '.sql_table('plugin').' WHERE pid='.$plugid); + + // 2. calculate new order number + $newOrder = ($oldOrder > 1) ? ($oldOrder - 1) : 1; + + // 3. update plug numbers + DB::execute('UPDATE '.sql_table('plugin').' SET porder='.$oldOrder.' WHERE porder='.$newOrder); + DB::execute('UPDATE '.sql_table('plugin').' SET porder='.$newOrder.' WHERE pid='.$plugid); + + //$this->action_pluginlist(); + // To avoid showing ticket in the URL, redirect to pluginlist, instead. + redirect($CONF['AdminURL'] . '?action=pluginlist'); + } + + /** + * @todo document this + */ + function action_plugindown() { + global $member, $manager, $CONF; + + // check if allowed + $member->isAdmin() or $this->disallow(); + + $plugid = intGetVar('plugid'); + if (!$manager->pidInstalled($plugid)) + $this->error(_ERROR_NOSUCHPLUGIN); + + // 1. get old order number + $oldOrder = DB::getValue('SELECT porder FROM '.sql_table('plugin').' WHERE pid='.$plugid); + + $res = DB::getResult('SELECT * FROM '.sql_table('plugin')); + $maxOrder = $res->rowCount(); + + // 2. calculate new order number + $newOrder = ($oldOrder < $maxOrder) ? ($oldOrder + 1) : $maxOrder; + + // 3. update plug numbers + DB::execute('UPDATE '.sql_table('plugin').' SET porder='.$oldOrder.' WHERE porder='.$newOrder); + DB::execute('UPDATE '.sql_table('plugin').' SET porder='.$newOrder.' WHERE pid='.$plugid); + + //$this->action_pluginlist(); + // To avoid showing ticket in the URL, redirect to pluginlist, instead. + redirect($CONF['AdminURL'] . '?action=pluginlist'); + } + ++======= ++>>>>>>> skinnable-master /** * Admin::action_pluginoptions() * @@@ -6886,82 -5128,29 +10992,90 @@@ * @return void * */ - public function action_pluginoptions($message = '') + static private function action_pluginoptions($message = '') { global $member, $manager; // check if allowed - $member->isAdmin() or $this->disallow(); + $member->isAdmin() or self::disallow(); - $pid = (integer) requestVar('plugid'); + $pid = intRequestVar('plugid'); if ( !$manager->pidInstalled($pid) ) { - $this->error(_ERROR_NOSUCHPLUGIN); + self::error(_ERROR_NOSUCHPLUGIN); + return; } ++<<<<<<< HEAD + $pname = $manager->getPluginNameFromPid($pid); + + /* NOTE: to include translation file */ + $manager->getPlugin($pname); + + $extrahead = "\n"; + $this->pagehead($extrahead); + echo '

(' . _PLUGS_BACK . ")

\n"; + echo '

' . sprintf(_PLUGIN_OPTIONS_TITLE, Entity::hsc($pname)) . "

\n"; + + if ( isset($message) ) + { + echo $message; + } + + echo "
\n"; + echo "
\n"; + echo "\n"; + echo "\n"; + $manager->addTicketHidden(); + + $options = array(); + $query = "SELECT * FROM %s WHERE ocontext='global' and opid=%d ORDER BY oid ASC"; + $query = sprintf($query, sql_table('plugin_option_desc'), $pid); + $result = DB::getResult($query); + foreach ( $result as $row ) + { + $options[$row['oid']] = array( + 'oid' => $row['oid'], + 'value' => $row['odef'], + 'name' => $row['oname'], + 'description' => $row['odesc'], + 'type' => $row['otype'], + 'typeinfo' => $row['oextra'], + 'contextid' => 0 + ); + } + // fill out actual values + if ( count($options) > 0 ) + { + $query = "SELECT oid, ovalue FROM %s WHERE oid in (%s)"; + $query = sprintf($query, sql_table('plugin_option'), implode(',',array_keys($options))); + $result = DB::getResult($query); + foreach ( $result as $row ) + { + $options[$row['oid']]['value'] = $row['ovalue']; + } + } + + // call plugins + $data = array('context' => 'global', 'plugid' => $pid, 'options'=>&$options); + $manager->notify('PrePluginOptionsEdit',$data); + + $template['content'] = 'plugoptionlist'; + $amount = showlist($options,'table', $template); + if ( $amount == 0 ) + { + echo '

',_ERROR_NOPLUGOPTIONS,'

'; ++======= + if ( isset($message) ) + { + self::$headMess = $message; ++>>>>>>> skinnable-master } - echo "
\n"; - echo "
\n"; - $this->pagefoot(); + $plugname = $manager->getPluginNameFromPid($pid); + $plugin = $manager->getPlugin($plugname); + self::$extrahead .= "\n"; + self::$skin->parse('pluginoptions'); return; } @@@ -6974,150 -5163,370 +11088,426 @@@ * @param void * @return void */ - public function action_pluginoptionsupdate() + static private function action_pluginoptionsupdate() { global $member, $manager; // check if allowed - $member->isAdmin() or $this->disallow(); + $member->isAdmin() or self::disallow(); + + $pid = intRequestVar('plugid'); - $pid = (integer) requestVar('plugid'); if ( !$manager->pidInstalled($pid) ) { - $this->error(_ERROR_NOSUCHPLUGIN); + self::error(_ERROR_NOSUCHPLUGIN); + return; } $aOptions = requestArray('plugoption'); NucleusPlugin::apply_plugin_options($aOptions); - $manager->notify('PostPluginOptionsUpdate',array('context' => 'global', 'plugid' => $pid)); + $data = array( + 'context' => 'global', + 'plugid' => $pid + ); + $manager->notify('PostPluginOptionsUpdate', $data); - $this->action_pluginoptions(_PLUGS_OPTIONS_UPDATED); + self::action_pluginoptions(_PLUGS_OPTIONS_UPDATED); return; } /** - * Admin::_insertPluginOptions() + * Admin::skineditgeneral() * - * Output plugin option field + * @param integer $skinid + * @param string $handler + * @return string empty or message if failed + */ + static private function skineditgeneral($skinid, $handler='') + { + global $manager; + + $name = postVar('name'); + $desc = postVar('desc'); + $type = postVar('type'); + $inc_mode = postVar('inc_mode'); + $inc_prefix = postVar('inc_prefix'); + + $skin =& $manager->getSkin($skinid, $handler); + + // 1. Some checks + if ( !isValidSkinName($name) ) + { + return _ERROR_BADSKINNAME; + } + + if ( ($skin->getName() != $name) && SKIN::exists($name) ) + { + return _ERROR_DUPSKINNAME; + } + + if ( !$type ) + { + $type = 'text/html'; + } + + if ( !$inc_mode ) + { + $inc_mode = 'normal'; + } + + // 2. Update description + $skin->updateGeneralInfo($name, $desc, $type, $inc_mode, $inc_prefix); + + return ''; + } + /** + * Admin::skindeleteconfirm() * - * @access public - * @param string $context plugin option context - * @param integer $contextid plugin option context id + * @param integer $skinid * @return void */ - public function _insertPluginOptions($context, $contextid = 0) + static private function skindeleteconfirm($skinid) + { + global $manager; + + if ( !in_array(self::$action, self::$adminskin_actions) ) + { + $event_identifier = 'Skin'; + } + else + { + $event_identifier = 'AdminSkin'; + } + + $data = array('skinid' => $skinid); + $manager->notify("PreDelete{$event_identifier}", $data); + + // 1. delete description + $query = "DELETE FROM %s WHERE sdnumber=%d;"; + $query = sprintf($query, sql_table('skin_desc'), (integer) $skinid); + DB::execute($query); + + // 2. delete parts + $query = "DELETE FROM %s WHERE sdesc=%d;"; + $query = sprintf($query, sql_table('skin'), (integer) $skinid); + DB::execute($query); + + $manager->notify("PostDelete{$event_identifier}", $data); + + return; + } + + /** + * Admin::skinremovetypeconfirm() + * + * @param integer $skinid + * @param string $skintype + * @return string empty or message if failed + */ + static private function skinremovetypeconfirm($skinid, $skintype) { global $manager; ++<<<<<<< HEAD + /* get current registered plugin option list in this context even if it's not used */ + $query = 'SELECT * FROM %s AS plugins, %s AS options LEFT OUTER JOIN %s AS added ' + . 'ON ( options.oid=added.oid ) ' + . 'WHERE plugins.pid=options.opid AND options.ocontext=%s AND added.ocontextid=%d ' + . 'ORDER BY options.oid ASC'; + $query = sprintf($query, sql_table('plugin'), sql_table('plugin_option_desc'), sql_table('plugin_option'), DB::quoteValue($context), intval($contextid)); + + $res = DB::getResult($query); + + $options = array(); + foreach ( $res as $row ) + { + /* NOTE: to include translation file */ + $manager->getPlugin($row['pfile']); + + $options[] = array( + 'pid' => $row['pid'], + 'pfile' => $row['pfile'], + 'oid' => $row['oid'], + 'value' => ( !$row['ovalue'] ) ? $row['odef'] : $row['ovalue'], + 'name' => $row['oname'], + 'description' => $row['odesc'], + 'type' => $row['otype'], + 'typeinfo' => $row['oextra'], + 'contextid' => $contextid, + 'extra' => '' + ); + } + + $manager->notify('PrePluginOptionsEdit',array('context' => $context, 'contextid' => $contextid, 'options'=>&$options)); + + $iPrevPid = -1; + foreach ( $options as $option) + { + // new plugin? + if ( $iPrevPid != $option['pid'] ) + { + $iPrevPid = $option['pid']; + if ( !defined('_PLUGIN_OPTIONS_TITLE') ) + { + define('_PLUGIN_OPTIONS_TITLE', 'Options for %s'); + } + echo "\n"; + echo '' . sprintf(_PLUGIN_OPTIONS_TITLE, Entity::hsc($option['pfile'])) . "\n"; + echo "\n"; + } + + $meta = NucleusPlugin::getOptionMeta($option['typeinfo']); + if ( @$meta['access'] != 'hidden' ) + { + echo ''; + listplug_plugOptionRow($option); + echo ''; ++======= + if ( !in_array(self::$action, self::$adminskin_actions) ) + { + $event_identifier = 'Skin'; + } + else + { + $event_identifier = 'AdminSkin'; + } + + if ( !isValidShortName($skintype) ) + { + return _ERROR_SKIN_PARTS_SPECIAL_DELETE; + } + + $data = array( + 'skinid' => $skinid, + 'skintype' => $skintype + ); + $manager->notify("PreDelete{$event_identifier}Part", $data); + + // delete part + $query = 'DELETE FROM %s WHERE sdesc = %d AND stype = %s;'; + $query = sprintf($query, sql_table('skin'), (integer) $skinid, DB::quoteValue($skintype) ); + DB::execute($query); + + $data = array( + 'skinid' => $skinid, + 'skintype' => $skintype + ); + $manager->notify("PostDelete{$event_identifier}Part", $data); + + return ''; + } + + /** + * Admin::skinclone() + * + * @param integer $skinid + * @param string $handler + * @return void + */ + static private function skinclone($skinid, $handler='') + { + global $manager; + + // 1. read skin to clone + $skin =& $manager->getSkin($skinid, $handler); + $name = "{$skin->getName()}_clone"; + + // if a skin with that name already exists: + if ( Skin::exists($name) ) + { + $i = 1; + while ( Skin::exists($name . $i) ) + { + $i++; + } + $name .= $i; + } + + // 2. create skin desc + $newid = Skin::createNew( + $name, + $skin->getDescription(), + $skin->getContentType(), + $skin->getIncludeMode(), + $skin->getIncludePrefix() + ); + + // 3. clone + $query = "SELECT stype FROM %s WHERE sdesc=%d;"; + $query = sprintf($query, sql_table('skin'), (integer) $skinid); + + $res = DB::getResult($query); + foreach ( $res as $row ) + { + $content = $skin->getContentFromDB($row['stype']); + if ( $content ) + { + $query = "INSERT INTO %s (sdesc, scontent, stype) VALUES (%d, %s, %s)"; + $query = sprintf($query, sql_table('skin'), (integer) $newid, DB::quoteValue($content), DB::quoteValue($row['stype'])); + DB::execute($query); ++>>>>>>> skinnable-master } } return; } /** - * Admin::input_yesno() - * Output input elements with radio attribute for yes/no options + * Admin::skinieimport() * - * @param string $name name attribute - * @param string $value_current current value attribute - * @param integer $tabindex tab index - * @param string $value_yes value attribute for yes option - * @param string $value_no value attribute for no option - * @param string $text_yes child text element for yes option - * @param string $text_no child text element for no option - * @param boolean $isAdmin have admin right or not - * @return void + * @param string $mode + * @param string $skinFileRaw + * @return string empty or message if failed + */ + static private function skinieimport($mode, $skinFileRaw) + { + global $DIR_LIBS, $DIR_SKINS; + + // load skinie class + include_once($DIR_LIBS . 'skinie.php'); + + $importer = new SkinImport(); + + // get full filename + if ( $mode == 'file' ) + { + $skinFile = $DIR_SKINS . $skinFileRaw . '/skinbackup.xml'; + } + else + { + $skinFile = $skinFileRaw; + } + + // read only metadata + $error = $importer->readFile($skinFile, 1); + if ( $error ) + { + unset($importer); + return $error; + } + + self::$contents['mode'] = $mode; + self::$contents['skinfile'] = $skinFileRaw; + self::$contents['skininfo'] = $importer->getInfo(); + self::$contents['skinnames'] = $importer->getSkinNames(); + self::$contents['tpltnames'] = $importer->getTemplateNames(); + + // clashes + $skinNameClashes = $importer->checkSkinNameClashes(); + $templateNameClashes = $importer->checkTemplateNameClashes(); + $hasNameClashes = (count($skinNameClashes) > 0) || (count($templateNameClashes) > 0); + + self::$contents['skinclashes'] = $skinNameClashes; + self::$contents['tpltclashes'] = $templateNameClashes; + self::$contents['nameclashes'] = $hasNameClashes ? 1 : 0; + + unset($importer); + return ''; + } + + /** + * Admin::skinieedoimport() + * + * @param string $mode + * @param string $skinFileRaw + * @param boolean $allowOverwrite + * @return string empty or message if failed */ - function input_yesno($name, $value_current, $tabindex = 0, $value_yes = 1, $value_no = 0, $text_yes = _YES, $text_no = _NO, $isAdmin = 0) + static private function skiniedoimport($mode, $skinFileRaw, $allowOverwrite) { - $id = preg_replace('#\[|\]#', '-', $name); - $id_yes = $id . $value_yes; - $id_no = $id . $value_no; + global $DIR_LIBS, $DIR_SKINS; + + // load skinie class + include_once($DIR_LIBS . 'skinie.php'); + + $importer = new SkinImport(); - /* yes option */ - echo 'readFile($skinFile); + if ( $error ) + { + unset($importer); + return $error; + } + + $error = $importer->writeToDatabase($allowOverwrite); + if ( $error ) + { + unset($importer); + return $error; + } + + self::$contents['mode'] = $mode; + self::$contents['skinfile'] = $skinFileRaw; + self::$contents['skininfo'] = $importer->getInfo(); + self::$contents['skinnames'] = $importer->getSkinNames(); + self::$contents['tpltnames'] = $importer->getTemplateNames(); + + unset($importer); + return ''; + } + + /** + * Admin::skinieexport() + * + * @param array $aSkins + * @param array $aTemplates + * @param string $info + * @return void + */ + static private function skinieexport($aSkins, $aTemplates, $info) + { + global $DIR_LIBS; + + // load skinie class + include_once($DIR_LIBS . 'skinie.php'); + + if ( !is_array($aSkins) ) { - echo " tabindex='$tabindex' checked='checked'"; + $aSkins = array(); } - echo " />\n"; - echo '\n"; - /* no option */ - echo 'addSkin($skinId); } - if ($isAdmin && $name=="canlogin") + foreach ( $templateList as $templateId ) { - echo ' disabled="disabled"'; + $exporter->addTemplate($templateId); } - echo " />\n"; - echo '\n"; + $exporter->setInfo($info); + $exporter->export(); return; } + + /** + * Admin::action_parseSpecialskin() + * + * @param void + * @return void + */ + static private function action_parseSpecialskin() + { + self::$skin->parse(self::$action); + return; + } } diff --combined nucleus/libs/BAN.php index cd8f8cf,18e034a..27f7af6 --- a/nucleus/libs/BAN.php +++ b/nucleus/libs/BAN.php @@@ -1,127 -1,110 +1,240 @@@ ++<<<<<<< HEAD +notify( + 'PreAddBan', + array( + 'blogid' => $blogid, + 'iprange' => &$iprange, + 'reason' => &$reason + ) + ); + + $query = 'INSERT INTO %s (blogid, iprange, reason) VALUES (%d, %s, %s)'; + $query = sprintf($query, sql_table('ban'), intval($blogid), DB::quoteValue($iprange), DB::quoteValue($reason)); + $res = DB::execute($query); + + $manager->notify( + 'PostAddBan', + array( + 'blogid' => $blogid, + 'iprange' => $iprange, + 'reason' => $reason + ) + ); + + return $res !== FALSE ? 1 : 0; + } + + /** + * Removes a ban from the banlist (correct iprange is needed as argument) + * Returns 1 on success, 0 on error + */ + public function removeBan($blogid, $iprange) + { + global $manager; + + $manager->notify( + 'PreDeleteBan', + array( + 'blogid' => $blogid, + 'range' => $iprange + ) + ); + + $query = 'DELETE FROM %s WHERE blogid=%d and iprange=%s'; + $query = sprintf($query, sql_table('ban'), intval($blogid), DB::quoteValue($iprange)); + $res = DB::execute($query); + + $manager->notify( + 'PostDeleteBan', + array( + 'blogid' => $blogid, + 'range' => $iprange + ) + ); + + return $res !== FALSE ? 1 : 0; + } +} + +class BanInfo +{ + public $iprange; + public $message; + + public function __construct($iprange, $message) + { + $this->iprange = $iprange; + $this->message = $message; + return; + } +} ++======= + $blogid, + 'iprange' => &$iprange, + 'reason' => &$reason + ); + $manager->notify('PreAddBan', $data); + + $query = 'INSERT INTO %s (blogid, iprange, reason) VALUES (%d, %s, %s)'; + $query = sprintf($query, sql_table('ban'), intval($blogid), DB::quoteValue($iprange), DB::quoteValue($reason)); + $res = DB::execute($query); + + $manager->notify('PostAddBan', $data); + + return $res !== FALSE ? 1 : 0; + } + + /** + * Removes a ban from the banlist (correct iprange is needed as argument) + * Returns 1 on success, 0 on error + */ + public function removeBan($blogid, $iprange) + { + global $manager; + + $data = array( + 'blogid' => $blogid, + 'range' => $iprange + ); + $manager->notify('PreDeleteBan', $data); + + $query = 'DELETE FROM %s WHERE blogid=%d and iprange=%s'; + $query = sprintf($query, sql_table('ban'), intval($blogid), DB::quoteValue($iprange)); + $res = DB::execute($query); + + $manager->notify('PostDeleteBan', $data); + + return $res !== FALSE ? 1 : 0; + } + } + + class BanInfo + { + public $iprange; + public $message; + + public function __construct($iprange, $message) + { + $this->iprange = $iprange; + $this->message = $message; + return; + } + } ++>>>>>>> skinnable-master diff --combined nucleus/libs/BLOG.php index f0f91a5,64ea623..bede7bd --- a/nucleus/libs/BLOG.php +++ b/nucleus/libs/BLOG.php @@@ -1,1918 -1,1928 +1,3849 @@@ ++<<<<<<< HEAD +blogid = (integer) $id; + $this->readSettings(); + $this->setSelectedCategory($catid); + return; + } + + /** + * Blog::readLog() + * Shows the given amount of items for this blog + * + * @param string $template String representing the template _NAME_ (!) + * @param integer $amountEntries amount of entries to show + * @param integer $startpos offset from where items should be shown (e.g. 5 = start at fifth item) + * @return integer amount of items shown + */ + public function readLog($template, $amountEntries, $offset = 0, $startpos = 0) + { + return $this->readLogAmount($template,$amountEntries,'','',1,1,$offset, $startpos); + } + + /** + * Blog::showArchive() + * Shows an archive for a given month + * + * @param integer $year year + * @param integer $month month + * @param string $template String representing the template name to be used + * @return void + */ + public function showArchive($templatename, $year, $month=0, $day=0) + { + // create extra where clause for select query + if ( $day == 0 && $month != 0 ) + { + $timestamp_start = mktime(0,0,0,$month,1,$year); + // also works when $month==12 + $timestamp_end = mktime(0,0,0,$month+1,1,$year); + } + elseif ( $month == 0 ) + { + $timestamp_start = mktime(0,0,0,1,1,$year); + // also works when $month==12 + $timestamp_end = mktime(0,0,0,12,31,$year); + } + else + { + $timestamp_start = mktime(0,0,0,$month,$day,$year); + $timestamp_end = mktime(0,0,0,$month,$day+1,$year); + } + $extra_query = " and i.itime>=%s and i.itime<%s"; + $extra_query = sprintf($extra_query, DB::formatDateTime($timestamp_start), DB::formatDateTime($timestamp_end)); + + $this->readLogAmount($templatename,0,$extra_query,'',1,1); + return; + } + + /** + * Blog::setSelectedCategory() + * Sets the selected category by id (only when category exists) + * + * @param integer $catid ID for category + * @return void + */ + public function setSelectedCategory($catid) + { + if ( $this->isValidCategory($catid) || (intval($catid) == 0) ) + { + $this->selectedcatid = intval($catid); + } + return; + } + + /** + * Blog::setSelectedCategoryByName() + * Sets the selected category by name + * + * @param string $catname name of category + * @return void + */ + public function setSelectedCategoryByName($catname) + { + $this->setSelectedCategory($this->getCategoryIdFromName($catname)); + return; + } + + /** + * Blog::getSelectedCategory() + * Returns the selected category + * + * @param void + * @return integer + */ + public function getSelectedCategory() + { + return $this->selectedcatid; + } + + /** + * Shows the given amount of items for this blog + * + * @param string $template string representing the template _NAME_ (!) + * @param integer $amountEntries amount of entries to show (0 = no limit) + * @param string $extraQuery extra conditions to be added to the query + * @param string $highlight contains a query that should be highlighted + * @param integer $comments 1=show comments 0=don't show comments + * @param integer $dateheads 1=show dateheads 0=don't show dateheads + * @param integer $offset offset + * @return integer amount of items shown + */ + private function readLogAmount($template, $amountEntries, $extraQuery, $highlight, $comments, $dateheads, $offset = 0, $startpos = 0) + { + $query = $this->getSqlBlog($extraQuery); + + if ( $amountEntries > 0 ) + { + // $offset zou moeten worden: + // (($startpos / $amountentries) + 1) * $offset ... later testen ... + $query .= ' LIMIT ' . intval($startpos + $offset).',' . intval($amountEntries); + } + return $this->showUsingQuery($template, $query, $highlight, $comments, $dateheads); + } + + /** + * Blog::showUsingQuery() + * Do the job for readLogAmmount + * + * @param string $templateName template name + * @param string $query string for query + * @param string $highlight string to be highlighted + * @param integer $comments the number of comments + * @param boolean $dateheads date header is needed or not + * @return integer the number of rows as a result of mysql query + */ + private function showUsingQuery($templateName, $query, $highlight = '', $comments = 0, $dateheads = 1) + { + global $CONF, $manager, $currentTemplateName; + + $lastVisit = cookieVar($CONF['CookiePrefix'] .'lastVisit'); + if ( $lastVisit != 0 ) + { + $lastVisit = $this->getCorrectTime($lastVisit); + } + + // set templatename as global variable (so plugins can access it) + $currentTemplateName = $templateName; + $template =& $manager->getTemplate($templateName); + + // create parser object & action handler + $handler = new ItemActions($this); + $handler->setTemplate($template); + $handler->setHighlight($highlight); + $handler->setLastVisit($lastVisit); + $handler->setShowComments($comments); + + $parser = new Parser($handler); + + // execute query + $items = DB::getResult($query); + + // loop over all items + $old_date = 0; + foreach ( $items as $item ) + { + // string timestamp -> unix timestamp + $item['timestamp'] = strtotime($item['itime']); + + // action handler needs to know the item we're handling + $handler->setCurrentItem($item); + + // add date header if needed + if ( $dateheads ) + { + $new_date = date('dFY', $item['timestamp']); + if ( $new_date != $old_date ) + { + // unless this is the first time, write date footer + $timestamp = $item['timestamp']; + if ( $old_date != 0 ) + { + $oldTS = strtotime($old_date); + $manager->notify('PreDateFoot',array('blog' => &$this, 'timestamp' => $oldTS)); + + if ( !in_array('DATE_FOOTER', $template) || empty($template['DATE_FOOTER']) ) + { + $tmp_footer = ''; + } + else + { + $tmp_footer = i18n::formatted_datetime($template['DATE_FOOTER'], $oldTS); + } + $parser->parse($tmp_footer); + $manager->notify('PostDateFoot',array('blog' => &$this, 'timestamp' => $oldTS)); + } + + $manager->notify('PreDateHead',array('blog' => &$this, 'timestamp' => $timestamp)); + + // note, to use templatvars in the dateheader, the %-characters need to be doubled in + // order to be preserved by strftime + if ( !in_array('DATE_HEADER', $template) || empty($template['DATE_HEADER']) ) + { + $tmp_header = ''; + } + else + { + $tmp_header = i18n::formatted_datetime($template['DATE_HEADER'], $timestamp); + } + $parser->parse($tmp_header); + $manager->notify('PostDateHead',array('blog' => &$this, 'timestamp' => $timestamp)); + } + $old_date = $new_date; + } + + // parse item + $parser->parse($template['ITEM_HEADER']); + $manager->notify('PreItem', array('blog' => &$this, 'item' => &$item)); + $parser->parse($template['ITEM']); + $manager->notify('PostItem', array('blog' => &$this, 'item' => &$item)); + $parser->parse($template['ITEM_FOOTER']); + } + + $numrows = $items->rowCount(); + + // add another date footer if there was at least one item + if ( ($numrows > 0) && $dateheads ) + { + $manager->notify('PreDateFoot',array('blog' => &$this, 'timestamp' => strtotime($old_date))); + $parser->parse($template['DATE_FOOTER']); + $manager->notify('PostDateFoot',array('blog' => &$this, 'timestamp' => strtotime($old_date))); + } + + $items->closeCursor(); + return $numrows; + } + + /** + * Blog::showOneitem() + * Simplified function for showing only one item + * + * @param integer $itemid ID for item + * @param array $template template for item + * @param string $highlight string for highlight + * @return integer 1 + */ + public function showOneitem($itemid, $template, $highlight) + { + $extraQuery = ' and inumber=' . intval($itemid); + + return $this->readLogAmount($template, 1, $extraQuery, $highlight, 0, 0); + } + + /** + * Blog::addItem() + * Adds an item to this blog + * + * @param integer $catid ID for category + * @param string $title ID for + * @param string $body text for body + * @param string $more text for more + * @param integer $blogid ID for blog + * @param integer $authorid ID for author + * @param timestamp $timestamp UNIX timestamp for post + * @param boolean $closed opened or closed + * @param boolean $draft draft or not + * @param boolean $posted posted or not + * @return integer ID for added item + */ + function additem($catid, $title, $body, $more, $blogid, $authorid, $timestamp, $closed, $draft, $posted='1') + { + global $manager; + + $blogid = (integer) $blogid; + $authorid = (integer) $authorid; + $title = $title; + $body = $body; + $more = $more; + $catid = intval($catid); + + // convert newlines to
+ if ( $this->convertBreaks() ) + { + $body = addBreaks($body); + $more = addBreaks($more); + } + + if ( $closed != '1' ) + { + $closed = '0'; + } + if ( $draft != '0' ) + { + $draft = '1'; + } + + if ( !$this->isValidCategory($catid) ) + { + $catid = $this->getDefaultCategory(); + } + + $isFuture = 0; + if ( $timestamp > $this->getCorrectTime() ) + { + $isFuture = 1; + } + + $timestamp = date('Y-m-d H:i:s',$timestamp); + + $manager->notify('PreAddItem',array('title' => &$title, 'body' => &$body, 'more' => &$more, 'blog' => &$this, 'authorid' => &$authorid, 'timestamp' => &$timestamp, 'closed' => &$closed, 'draft' => &$draft, 'catid' => &$catid)); + + $ititle = DB::quoteValue($title); + $ibody = DB::quoteValue($body); + $imore = DB::quoteValue($more); + $timestamp = DB::formatDateTime(strtotime($timestamp)); + + $query = "INSERT INTO %s (ITITLE, IBODY, IMORE, IBLOG, IAUTHOR, ITIME, ICLOSED, IDRAFT, ICAT, IPOSTED) VALUES (%s, %s, %s, %d, %d, %s, %s, %s, %s, %s)"; + $query = sprintf($query, sql_table('item'), $ititle, $ibody, $imore, $blogid, $authorid, $timestamp, $closed, $draft, $catid, $posted); + DB::execute($query); + $itemid = DB::getInsertId(); + + $manager->notify('PostAddItem',array('itemid' => $itemid)); + + if ( !$draft ) + { + $this->updateUpdateFile(); + } + // send notification mail + if ( !$draft && !$isFuture && $this->getNotifyAddress() && $this->notifyOnNewItem() ) + { + $this->sendNewItemNotification($itemid, $title, $body); + } + return $itemid; + } + + /** + * Blog::sendNewItemNotification() + * Send a new item notification to the notification list + * + * @param string $itemid ID of the item + * @param string $title title of the item + * @param string $body body of the item + * @return void + */ + public function sendNewItemNotification($itemid, $title, $body) + { + global $CONF, $member; + + $ascii = Entity::anchor_footnoting($body); + + $message = _NOTIFY_NI_MSG . " \n"; + $temp = parse_url($CONF['Self']); + if ( $temp['scheme'] ) + { + $message .= Link::create_item_link($itemid) . "\n\n"; + } + else + { + $tempurl = $this->getURL(); + if ( i18n::substr($tempurl, -1) == '/' || i18n::substr($tempurl, -4) == '.php' ) + { + $message .= $tempurl . '?itemid=' . $itemid . "\n\n"; + } + else + { + $message .= $tempurl . '/?itemid=' . $itemid . "\n\n"; + } + } + $message .= _NOTIFY_TITLE . ' ' . strip_tags($title) . "\n"; + $message .= _NOTIFY_CONTENTS . "\n " . $ascii . "\n"; + $message .= NOTIFICATION::get_mail_footer(); + + $subject = $this->getName() . ': ' . _NOTIFY_NI_TITLE; + + $from = $member->getNotifyFromMailAddress(); + + NOTIFICATION::mail($this->getNotifyAddress(), $subject, $message, $from, i18n::get_current_charset()); + return; + } + + /** + * Blog::createNewCategory() + * Creates a new category for this blog + * + * @param string $catName name of the new category. When empty, a name is generated automatically (starting with newcat) + * @param string $catDescription description of the new category. Defaults to 'New Category' + * @return integer ID for new category on success. 0 on failure + */ + public function createNewCategory($catName = '', $catDescription = _CREATED_NEW_CATEGORY_DESC) + { + global $member, $manager; + + if ( !$member->blogAdminRights($this->blogid) ) + { + return 0; + } + + // generate + if ( $catName == '' ) + { + $catName = _CREATED_NEW_CATEGORY_NAME; + $i = 1; + + $res = DB::getResult('SELECT * FROM '.sql_table('category')." WHERE cname='".$catName.$i."' and cblog=".$this->blogid); + while ( $res->rowCount() > 0 ) + { + $i++; + $res = DB::getResult('SELECT * FROM '.sql_table('category')." WHERE cname='".$catName.$i."' and cblog=".$this->blogid); + } + + $catName = $catName . $i; + } + + $data = array( + 'blog' => &$this, + 'name' => &$catName, + 'description' => $catDescription + ); + $manager->notify('PreAddCategory', $data); + + $query = "INSERT INTO %s (cblog, cname, cdesc) VALUES (%d, %s, %s)"; + $query = sprintf($query, sql_table('category'), (integer) $this->blogid, DB::quoteValue($catName), DB::quoteValue($catDescription)); + DB::execute($query); + $catid = DB::getInsertId(); + + $data = array( + 'blog' => &$this, + 'name' => $catName, + 'description' => $catDescription, + 'catid' => $catid + ); + $manager->notify('PostAddCategory', $data); + + return $catid; + } + + /** + * Blog::search() + * Searches all months of this blog for the given query + * + * @param string $query search query + * @param array $template template to be used (__NAME__ of the template) + * @param integer $amountMonths max amount of months to be search (0 = all) + * @param integer $maxresults max number of results to show + * @param integer $startpos offset + * @return amount of hits found + */ + public function search($query, $template, $amountMonths, $maxresults, $startpos) { + global $CONF, $manager; + + $highlight = ''; + $sqlquery = $this->getSqlSearch($query, $amountMonths, $highlight); + + if ( $sqlquery == '' ) + { + // no query -> show everything + $extraquery = ''; + $amountfound = $this->readLogAmount($template, $maxresults, $extraQuery, $query, 1, 1); + } + else + { + // add LIMIT to query (to split search results into pages) + if ( intval($maxresults > 0) ) + { + $sqlquery .= ' LIMIT ' . intval($startpos) . ',' . intval($maxresults); + } + + // show results + $amountfound = $this->showUsingQuery($template, $sqlquery, $highlight, 1, 1); + + // when no results were found, show a message + if ( $amountfound == 0 ) + { + $template =& $manager->getTemplate($template); + $vars = array( + 'query' => Entity::hsc($query), + 'blogid' => $this->blogid + ); + echo Template::fill($template['SEARCH_NOTHINGFOUND'], $vars); + } + } + return $amountfound; + } + + /** + * Blog::getSqlSearch() + * Returns an SQL query to use for a search query + * No LIMIT clause is added. (caller should add this if multiple pages are requested) + * + * @param string $query search query + * @param integer $amountMonths amount of months to search back. Default = 0 = unlimited + * @param string $mode either empty, or 'count'. In this case, the query will be a SELECT COUNT(*) query + * @return string $highlight words to highlight (out parameter) + * @return string either a full SQL query, or an empty string (if querystring empty) + */ + public function getSqlSearch($query, $amountMonths = 0, &$highlight, $mode = '') + { + $searchclass = new Search($query); + + $highlight = $searchclass->inclusive; + + // if querystring is empty, return empty string + if ( $searchclass->inclusive == '' ) + { + return ''; + } + + $where = $searchclass->boolean_sql_where('ititle,ibody,imore'); + $select = $searchclass->boolean_sql_select('ititle,ibody,imore'); + + // get list of blogs to search + $blogs = $searchclass->blogs; // array containing blogs that always need to be included + $blogs[] = $this->blogid; // also search current blog (duh) + $blogs = array_unique($blogs); // remove duplicates + $selectblogs = ''; + if ( count($blogs) > 0 ) + { + $selectblogs = ' and i.iblog in (' . implode(',', $blogs) . ')'; + } + + if ( $mode == '' ) + { + $query = 'SELECT i.inumber as itemid, i.ititle as title, i.ibody as body, i.itime, i.imore as more, i.icat as catid, i.iclosed as closed, + m.mname as author, m.mrealname as authorname, m.mnumber as authorid, m.memail as authormail, m.murl as authorurl, + c.cname as category'; + + if ( $select ) + { + $query .= ', '.$select. ' as score '; + } + } + else + { + $query = 'SELECT COUNT(*) as result '; + } + + $query .= ' FROM '.sql_table('item').' as i, '.sql_table('member').' as m, '.sql_table('category').' as c' + . ' WHERE i.iauthor=m.mnumber' + . ' and i.icat=c.catid' + // exclude drafts + . ' and i.idraft=0' + . $selectblogs + // don't show future items + . ' and i.itime<=' . DB::formatDateTime($this->getCorrectTime()) + . ' and '.$where; + + // take into account amount of months to search + if ( $amountMonths > 0 ) + { + $localtime = getdate($this->getCorrectTime()); + $timestamp_start = mktime(0,0,0,$localtime['mon'] - $amountMonths,1,$localtime['year']); + $query .= ' and i.itime>' . DB::formatDateTime($timestamp_start); + } + + if ( $mode == '' ) + { + if ( $select ) + { + $query .= ' ORDER BY score DESC'; + } + else + { + $query .= ' ORDER BY i.itime DESC '; + } + } + + return $query; + } + + /** + * Blog::getSqlBlog() + * Returns the SQL query that's normally used to display the blog items on the index type skins + * No LIMIT clause is added. (caller should add this if multiple pages are requested) + * + * @param string $extraQuery extra query string + * @param string $mode either empty, or 'count'. In this case, the query will be a SELECT COUNT(*) query + * @return string either a full SQL query, or an empty string + */ + public function getSqlBlog($extraQuery, $mode = '') + { + if ( $mode == '' ) + { + $query = 'SELECT i.inumber as itemid, i.ititle as title, i.ibody as body, m.mname as author, + m.mrealname as authorname, i.itime, i.imore as more, m.mnumber as authorid, m.memail as authormail, + m.murl as authorurl, c.cname as category, i.icat as catid, i.iclosed as closed'; + } + else + { + $query = 'SELECT COUNT(*) as result '; + } + + $query .= ' FROM '.sql_table('item').' as i, '.sql_table('member').' as m, '.sql_table('category').' as c' + . ' WHERE i.iblog='.$this->blogid + . ' and i.iauthor=m.mnumber' + . ' and i.icat=c.catid' + . ' and i.idraft=0' // exclude drafts + . ' and i.itime<=' . DB::formatDateTime($this->getCorrectTime()); // don't show future items + + if ( $this->selectedcatid ) + { + $query .= ' and i.icat=' . $this->selectedcatid . ' '; + } + + $query .= $extraQuery; + + if ( $mode == '' ) + { + $query .= ' ORDER BY i.itime DESC'; + } + return $query; + } + + /** + * Blog::showArchiveList() + * Shows the archivelist using the given template + * + * @param string $template template name + * @param string $mode year/month/day + * @param integer $limit limit of record count + * @return void + */ + public function showArchiveList($template, $mode = 'month', $limit = 0) + { + global $CONF, $catid, $manager; + + if ( !isset ($linkparams) ) + { + $linkparams = array(); + } + + if ( $catid ) + { + $linkparams = array('catid' => $catid); + } + + $template =& $manager->getTemplate($template); + $data['blogid'] = $this->blogid; + + if ( !array_key_exists('ARCHIVELIST_HEADER', $template) || !$template['ARCHIVELIST_HEADER'] ) + { + $tplt = ''; + } + else + { + $tplt = $template['ARCHIVELIST_HEADER']; + } + + echo Template::fill($tplt, $data); + + $query = 'SELECT itime, SUBSTRING(itime,1,4) AS Year, SUBSTRING(itime,6,2) AS Month, SUBSTRING(itime,9,2) AS Day' + . ' FROM '.sql_table('item') + . ' WHERE iblog=' . $this->blogid + . ' AND itime <=' . DB::formatDateTime($this->getCorrectTime()) // don't show future items! + . ' AND idraft=0'; // don't show draft items + + if ( $catid ) + { + $query .= ' and icat=' . intval($catid); + } + + $query .= ' GROUP BY Year'; + if ( $mode == 'month' || $mode == 'day' ) + { + $query .= ', Month'; + } + if ( $mode == 'day' ) + { + $query .= ', Day'; + } + + $query .= ' ORDER BY itime DESC'; + + if ( $limit > 0 ) + { + $query .= ' LIMIT ' . intval($limit); + } + + $res = DB::getResult($query); + foreach ( $res as $current ) + { + /* string time -> unix timestamp */ + $current['itime'] = strtotime($current['itime']); + + if ( $mode == 'day' ) + { + $archivedate = date('Y-m-d',$current['itime']); + $archive['day'] = date('d',$current['itime']); + $data['day'] = date('d',$current['itime']); + $data['month'] = date('m',$current['itime']); + $archive['month'] = $data['month']; + } + elseif ( $mode == 'year' ) + { + $archivedate = date('Y',$current['itime']); + $data['day'] = ''; + $data['month'] = ''; + $archive['day'] = ''; + $archive['month'] = ''; + } + else + { + $archivedate = date('Y-m',$current['itime']); + $data['month'] = date('m',$current['itime']); + $archive['month'] = $data['month']; + $data['day'] = ''; + $archive['day'] = ''; + } + + $data['year'] = date('Y',$current['itime']); + $archive['year'] = $data['year']; + $data['archivelink'] = Link::create_archive_link($this->blogid,$archivedate,$linkparams); + + $manager->notify('PreArchiveListItem', array('listitem' => &$data)); + + $temp = Template::fill($template['ARCHIVELIST_LISTITEM'],$data); + echo i18n::formatted_datetime($temp, $current['itime']); + return; + } + + $res->closeCursor(); + + if ( !array_key_exists('ARCHIVELIST_FOOTER', $template) || !$template['ARCHIVELIST_FOOTER'] ) + { + $tplt = ''; + } + else + { + $tplt = $template['ARCHIVELIST_FOOTER']; + } + + echo Template::fill($tplt, $data); + return; + } + + /** + * Blog::showCategoryList() + * Shows the list of categories using a given template + * + * @param string $template Template Name + * @return void + */ + public function showCategoryList($template) + { + global $CONF, $archive, $archivelist, $manager; + + /* + * determine arguments next to catids + * I guess this can be done in a better way, but it works + */ + $linkparams = array(); + if ( $archive ) + { + $blogurl = Link::create_archive_link($this->blogid, $archive, ''); + $linkparams['blogid'] = $this->blogid; + $linkparams['archive'] = $archive; + } + else if ( $archivelist ) + { + $blogurl = Link::create_archivelist_link($this->blogid, ''); + $linkparams['archivelist'] = $archivelist; + } + else + { + $blogurl = Link::create_blogid_link($this->blogid, ''); + $linkparams['blogid'] = $this->blogid; + } + + $template =& $manager->getTemplate($template); + + //: Change: Set nocatselected variable + if ( $this->selectedcatid ) + { + $nocatselected = 'no'; + } + else + { + $nocatselected = 'yes'; + } + + $args = array( + 'blogid' => $this->blogid, + 'blogurl' => $blogurl, + 'self' => $CONF['Self'], + 'catiscurrent' => $nocatselected, // Change: Set catiscurrent template variable for header + 'currentcat' => $nocatselected + ); + + /* output header of category list item */ + if ( !array_key_exists('CATLIST_HEADER', $template) || empty($template['CATLIST_HEADER']) ) + { + echo Template::fill(NULL, $args); + } + else + { + echo Template::fill($template['CATLIST_HEADER'], $args); + } + + $query = "SELECT catid, cdesc as catdesc, cname as catname FROM %s WHERE cblog=%d ORDER BY cname ASC;"; + $query = sprintf($query, sql_table('category'), (integer) $this->blogid); + $res = DB::getResult($query); + + foreach ( $res as $data ) + { + $args = array( + 'catid' => $data['catid'], + 'name' => $data['catname'], + 'extra' => $linkparams + ); + + $data['blogid'] = $this->blogid; + $data['blogurl'] = $blogurl; + $data['catlink'] = Link::create_link('category', $args); + $data['self'] = $CONF['Self']; + + // this gives catiscurrent = no when no category is selected. + $data['catiscurrent'] = 'no'; + $data['currentcat'] = 'no'; + + if ( $this->selectedcatid ) + { + if ( $this->selectedcatid == $data['catid'] ) + { + $data['catiscurrent'] = 'yes'; + $data['currentcat'] = 'yes'; + } + } + else + { + global $itemid; + if ( intval($itemid) && $manager->existsItem(intval($itemid), 0, 0) ) + { + $iobj =& $manager->getItem(intval($itemid), 0, 0); + $cid = $iobj['catid']; + + if ( $cid == $data['catid'] ) + { + $data['catiscurrent'] = 'yes'; + $data['currentcat'] = 'yes'; + } + } + } + + $manager->notify('PreCategoryListItem', array('listitem' => &$data)); + + if ( !array_key_exists('CATLIST_LISTITEM', $template) || empty($template['CATLIST_LISTITEM'])) + { + echo Template::fill(NULL, $data); + } + else + { + echo Template::fill($template['CATLIST_LISTITEM'], $data); + } + } + + $res->closeCursor(); + + $args = array( + 'blogid' => $this->blogid, + 'blogurl' => $blogurl, + 'self' => $CONF['Self'], + 'catiscurrent' => $nocatselected, //: Change: Set catiscurrent template variable for footer + 'currentcat' => $nocatselected + ); + + if ( !array_key_exists('CATLIST_FOOTER', $template) || empty($template['CATLIST_FOOTER'])) + { + echo Template::fill(NULL, $args); + } + else + { + echo Template::fill($template['CATLIST_FOOTER'], $args); + } + + return; + } + + /** + * Blog::showBlogList() + * Shows a list of all blogs in the system using a given template + * ordered by number, name, shortname or description + * in ascending or descending order + * + * @param string $template tempalte name + * @param string $bnametype bname/bshortname + * @param string $orderby string for 'ORDER BY' SQL + * @param string $direction ASC/DESC + * @return void + */ + public function showBlogList($template, $bnametype, $orderby, $direction) + { + global $CONF, $manager; + + switch ( $orderby ) + { + case 'number': + $orderby='bnumber'; + break; + case 'name': + $orderby='bname'; + break; + case 'shortname': + $orderby='bshortname'; + break; + case 'description': + $orderby='bdesc'; + break; + default: + $orderby='bnumber'; + break; + } + + $direction=strtolower($direction); + switch ( $direction ) + { + case 'asc': + $direction='ASC'; + break; + case 'desc': + $direction='DESC'; + break; + default: + $direction='ASC'; + break; + } + + $template =& $manager->getTemplate($template); + + if ( array_key_exists('BLOGLIST_HEADER', $template) && !empty($template['BLOGLIST_HEADER']) ) + { + $vars = array( + 'sitename' => $CONF['SiteName'], + 'siteurl' => $CONF['IndexURL'] + ); + + echo Template::fill($template['BLOGLIST_HEADER'], $vars); + } + + if ( array_key_exists('BLOGLIST_LISTITEM', $template) && !empty($template['BLOGLIST_LISTITEM']) ) + { + $query = 'SELECT bnumber, bname, bshortname, bdesc, burl FROM '.sql_table('blog').' ORDER BY '.$orderby.' '.$direction; + $res = DB::getResult($query); + + foreach ( $res as $data ) + { + $list = array(); + $list['bloglink'] = Link::create_blogid_link($data['bnumber']); + $list['blogdesc'] = $data['bdesc']; + $list['blogurl'] = $data['burl']; + + if ( $bnametype == 'shortname' ) + { + $list['blogname'] = $data['bshortname']; + } + else + { + /* all other cases */ + $list['blogname'] = $data['bname']; + } + + $manager->notify('PreBlogListItem',array('listitem' => &$list)); + + echo Template::fill($template['BLOGLIST_LISTITEM'], $list); + } + + $res->closeCursor(); + } + + + if ( array_key_exists('BLOGLIST_FOOTER', $template) && !empty($template['BLOGLIST_FOOTER']) ) + { + $vars = array( + 'sitename' => $CONF['SiteName'], + 'siteurl' => $CONF['IndexURL'] + ); + echo Template::fill($template['BLOGLIST_FOOTER']); + } + return; + } + + /** + * Blog::readSettings() + * Read the blog settings + * + * @param void + * @return void + */ + public function readSettings() + { + $query = 'SELECT * FROM %s WHERE bnumber=%d;'; + $query = sprintf($query, sql_table('blog'), (integer) $this->blogid); + $res = DB::getResult($query); + + $this->isValid = ($res->rowCount() > 0); + if ( $this->isValid ) + { + $this->settings = $res->fetch(PDO::FETCH_ASSOC); + } + return; + } + + /** + * Blog::writeSettings() + * Write the blog settings + */ + public function writeSettings() + { + // (can't use floatval since not available prior to PHP 4.2) + $offset = $this->getTimeOffset(); + if ( !is_float($offset) ) + { + $offset = (integer) $offset; + } + + $query = 'UPDATE '.sql_table('blog') + . ' SET bname=' . DB::quoteValue($this->getName()) . ',' + . ' bshortname='. DB::quoteValue($this->getShortName()) . ',' + . ' bcomments='. intval($this->commentsEnabled()) . ',' + . ' bmaxcomments=' . intval($this->getMaxComments()) . ',' + . ' btimeoffset=' . $offset . ',' + . ' bpublic=' . intval($this->isPublic()) . ',' + . ' breqemail=' . intval($this->emailRequired()) . ',' + . ' bconvertbreaks=' . intval($this->convertBreaks()) . ',' + . ' ballowpast=' . intval($this->allowPastPosting()) . ',' + . ' bnotify=' . DB::quoteValue($this->getNotifyAddress()) . ',' + . ' bnotifytype=' . intval($this->getNotifyType()) . ',' + . ' burl=' . DB::quoteValue($this->getURL()) . ',' + . ' bupdate=' . DB::quoteValue($this->getUpdateFile()) . ',' + . ' bdesc=' . DB::quoteValue($this->getDescription()) . ',' + . ' bdefcat=' . intval($this->getDefaultCategory()) . ',' + . ' bdefskin=' . intval($this->getDefaultSkin()) . ',' + . ' bincludesearch=' . intval($this->getSearchable()) + . ' WHERE bnumber=' . intval($this->blogid); + DB::execute($query); + return; + } + + /** + * Blog::updateUpdatefile() + * Update the update file if requested + * + * @param void + * @return void + */ + public function updateUpdatefile() + { + if ( $this->getUpdateFile() ) + { + $f_update = fopen($this->getUpdateFile(), 'w'); + fputs($f_update,$this->getCorrectTime()); + fclose($f_update); + } + return; + } + + /** + * Blog::isValidCategory() + * Check if a category with a given catid is valid + * + * @param integer $catid ID for category + * @return boolean exists or not + */ + public function isValidCategory($catid) + { + $query = 'SELECT * FROM %s WHERE cblog=%d and catid=%d;'; + $query = sprintf($query, sql_table('category'), (integer) $this->blogid, (integer) $catid); + $res = DB::getResult($query); + return ($res->rowCount() != 0); + } + + /** + * Blog::getCategoryName() + * Get the category name for a given catid + * + * @param integer $catid ID for category + * @return string name of category + */ + public function getCategoryName($catid) + { + $query = 'SELECT cname FROM %s WHERE cblog=%d and catid=%d;'; + $query = sprintf($query, sql_table('category'), (integer) $this->blogid, (integer) $catid); + $res = DB::getValue($query); + return $res; + } + + /** + * Blog::getCategoryDesc() + * Get the category description for a given catid + * + * @param $catid + * category id + */ + public function getCategoryDesc($catid) + { + $query = 'SELECT cdesc FROM %s WHERE cblog=%d and catid=%d;'; + $query = sprintf($querym, sql_table('category'), (integer) $this->blogid, (integer) $catid); + $res = DB::getValue(); + return $res; + } + + /** + * Blog::getCategoryIdFromName + * Get the category id for a given category name + * + * @param string $name category name + * @return ID for category + */ + public function getCategoryIdFromName($name) + { + $query = 'SELECT catid FROM %s WHERE cblog=%d and cname=%s;'; + $query = sprintf($query, sql_table('category'), (integer) $this->blogid, DB::quoteValue($name)); + + $res = DB::getValue(); + if ( !$res ) + { + return $this->getDefaultCategory(); + } + return $res; + } + + /** + * Blog::insertJavaScriptInfo() + * Insert a javascript that includes information about the settings + * of an author: ConvertBreaks, MediaUrl and AuthorId + * + * @param $authorid id of the author + */ + public function insertJavaScriptInfo($authorid = '') + { + global $member, $CONF; + + if ( $authorid == '' ) + { + $authorid = $member->getID(); + } + + echo "\n"; + return; + } + + /** + * Blog::setAllowPastPosting() + * Set the the setting for allowing to publish postings in the past + * + * @param boolean $val new value for ballowpast + * @return void + */ + public function setAllowPastPosting($val) + { + $this->setSetting('ballowpast', $val); + return; + } + + /** + * Blog::allowPastPosting() + * Get the the setting if it is allowed to publish postings in the past + * [should be named as getAllowPastPosting()] + * + * @param void + * @return boolean + */ + public function allowPastPosting() + { + return $this->getSetting('ballowpast'); + } + + /** + * Blog::getCorrectTime() + * + * @param integer $t + * @return integer + */ + public function getCorrectTime($t=0) + { + if ( $t == 0 ) + { + $t = time(); + } + return ($t + 3600 * $this->getTimeOffset()); + } + + /** + * Blog::getName() + * + * @param void + * @return string name of this weblog + */ + public function getName() + { + return $this->getSetting('bname'); + } + + /** + * Blog::getShortName() + * + * @param void + * @return string short name of this weblog + */ + public function getShortName() + { + return $this->getSetting('bshortname'); + } + + /** + * Blog::getMaxComments() + * + * @param void + * @return integer maximum number of comments + */ + public function getMaxComments() + { + return $this->getSetting('bmaxcomments'); + } + + /** + * Blog::getNotifyAddress() + * + * @param void + * @return string mail address for notifying + */ + public function getNotifyAddress() + { + return $this->getSetting('bnotify'); + } + + /** + * Blog::getNotifyType() + * + * @param void + * @return integer notifycation type + */ + public function getNotifyType() + { + return $this->getSetting('bnotifytype'); + } + + /** + * Blog::notifyOnComment() + * + * @param void + * @return boolean + */ + public function notifyOnComment() + { + $n = $this->getNotifyType(); + return (($n != 0) && (($n % 3) == 0)); + } + + /** + * Blog::notifyOnVote() + * + * @param void + * @return boolean + */ + public function notifyOnVote() + { + $n = $this->getNotifyType(); + return (($n != 0) && (($n % 5) == 0)); + } + + /** + * Blog::notifyOnNewItem() + * + * @param void + * @return boolean + */ + public function notifyOnNewItem() + { + $n = $this->getNotifyType(); + return (($n != 0) && (($n % 7) == 0)); + } + + /** + * Blog::setNotifyType() + * + * @param integer $val + * @return void + */ + public function setNotifyType($val) + { + $this->setSetting('bnotifytype',$val); + return; + } + + /** + * Blog::getTimeOffset() + * @param void + * @return + */ + public function getTimeOffset() + { + return $this->getSetting('btimeoffset'); + } + + /** + * Blog::commentsEnabled() + * @param void + * @return integer enabled or not + */ + public function commentsEnabled() + { + return $this->getSetting('bcomments'); + } + + /** + * Blog::getURL() + * @param void + * @return string URI for this weblog + */ + public function getURL() + { + return $this->getSetting('burl'); + } + + /** + * Blog::getDefaultSkin() + * @param void + * @return name of skin as default for this weblog + */ + public function getDefaultSkin() + { + return $this->getSetting('bdefskin'); + } + + /** + * Blog::getUpdateFile() + * @param void + * @return string name of file to be updated when weblog is updated + */ + public function getUpdateFile() + { + return $this->getSetting('bupdate'); + } + + /** + * Blog::getDescription() + * @param void + * @return string description for this weblog + */ + public function getDescription() + { + return $this->getSetting('bdesc'); + } + + /** + * Blog::isPublic() + * @param void + * @return integer publlic or not + */ + public function isPublic() + { + return $this->getSetting('bpublic'); + } + + /** + * Blog::emailRequired() + * @param void + * @return integer email is required when posting comment or not + */ + public function emailRequired() + { + return $this->getSetting('breqemail'); + } + + /** + * Blog::getSearchable() + * @param void + * @return integer searchable or not + */ + public function getSearchable() + { + return $this->getSetting('bincludesearch'); + } + + /** + * Blog::getDefaultCategory() + * @param void + * @return ID for category as a default + */ + public function getDefaultCategory() + { + return $this->getSetting('bdefcat'); + } + + /** + * Blog::setPublic() + * @param integer $val allow comments by non-registered members or not + * @return void + */ + public function setPublic($val) + { + $this->setSetting('bpublic', $val); + return; + } + + /** + * Blog::setSearchable() + * @param integer $val searchable from the other blogs or not + * @return void + */ + public function setSearchable($val) + { + $this->setSetting('bincludesearch', $val); + return; + } + + /** + * Blog::setDescription + * @param string $val description for this weblog + * @return void + */ + public function setDescription($val) + { + $this->setSetting('bdesc',$val); + return; + } + + /** + * Blog::setUpdateFile() + * @param string $val name of file to beupdated when weblog is updated + * @return + */ + public function setUpdateFile($val) + { + $this->setSetting('bupdate',$val); + return; + } + + /** + * Blog::setDefaultSkin() + * @param integer $val ID for default skin to use when displaying this weblog + * @return void + */ + public function setDefaultSkin($val) + { + $this->setSetting('bdefskin', $val); + return; + } + + /** + * Blog::setURL() + * @param string $val URI for this weblog + * @return + */ + public function setURL($val) + { + $this->setSetting('burl', $val); + return; + } + + /** + * Blog::setName() + * @param string $val name of this weblog + * @return void + */ + public function setName($val) + { + $this->setSetting('bname', $val); + return; + } + + /** + * Blog::setShortName() + * @param string $val short name for this weblog + * @return void + */ + public function setShortName($val) + { + $this->setSetting('bshortname', $val); + return; + } + + /** + * Blog::setCommentsEnabled() + * @param integer $val enabling posting comment or not + * @return void + */ + public function setCommentsEnabled($val) + { + $this->setSetting('bcomments',$val); + return; + } + + /** + * Blog::setMaxComments() + * @param integer $val maximum number of comments for this weblog + * @return void + */ + public function setMaxComments($val) + { + $this->setSetting('bmaxcomments', $val); + return; + } + + /** + * Blog::setNotifyAddress() + * @param string $val email to be notified if weblog updated + * @return void + */ + public function setNotifyAddress($val) + { + $this->setSetting('bnotify', $val); + return; + } + + /** + * Blog::setEmailRequired() + * @param string requiring comments with email or not from non member + * @return void + */ + public function setEmailRequired($val) + { + $this->setSetting('breqemail', $val); + return; + } + + /** + * Blog::setTimeOffset() + * @param integer $val time offset + * @return void + */ + public function setTimeOffset($val) + { + // check validity of value + // 1. replace , by . (common mistake) + $val = str_replace(',','.',$val); + + // 2. cast to float or int + if ( is_numeric($val) && (i18n::strpos($val, '.5') === (i18n::strlen($val) - 2)) ) + { + $val = (float) $val; + } + else + { + $val = (integer) $val; + } + + $this->setSetting('btimeoffset',$val); + return; + } + + /** + * Blog::setDefaultCategory() + * @param integer $val ID for default category for this weblog + * @return + */ + public function setDefaultCategory($val) + { + $this->setSetting('bdefcat',$val); + return; + } + + /** + * Blog::getSetting() + * @param string $key key for setting of this weblog + * @return mixed value for the setting + */ + public function getSetting($key) + { + return $this->settings[$key]; + } + + /** + * Blog::setSetting() + * @param string $key key for setting of this weblog + * @param mixed $value value for the key + * @return + */ + public function setSetting($key, $value) + { + $this->settings[$key] = $value; + return; + } + + /** + * Blog::addTeamMember() + * Tries to add a member to the team. + * Returns false if the member was already on the team + * + * @param integer $memberid id for member + * @param boolean $admin super-admin or not + * @return boolean Success/Fail + */ + public function addTeamMember($memberid, $admin) + { + global $manager; + + $memberid = intval($memberid); + $admin = intval($admin); + + // check if member is already a member + $tmem =& $manager->getMember($memberid); + + if ( $tmem->isTeamMember($this->blogid) ) + { + return 0; + } + + $data = array( + 'blog' => &$this, + 'member' => &$tmem, + 'admin' => &$admin + ); + $manager->notify('PreAddTeamMember', $data); + + // add to team + $query = "INSERT INTO %s (TMEMBER, TBLOG, TADMIN) VALUES (%d, %d, %d);"; + $query = sprintf($query, sql_table('team'), (integer) $memberid, (integer) $this->blogid, (integer) $admin); + DB::execute($query); + + $data = array( + 'blog' => &$this, + 'member' => &$tmem, + 'admin' => $admin + ); + $manager->notify('PostAddTeamMember', $data); + + $logMsg = sprintf(_TEAM_ADD_NEWTEAMMEMBER, $tmem->getDisplayName(), $memberid, $this->getName()); + ActionLog::add(INFO, $logMsg); + + return 1; + } + + /** + * Blog::getID() + * @param void + * @return integer ID for this weblog + */ + public function getID() + { + return (integer) $this->blogid; + } + + /** + * Checks if a blog with a given shortname exists + * Returns true if there is a blog with the given shortname (static) + * + * @param string $name blog shortname + * @return boolean exists or not + */ + public function exists($name) + { + $r = DB::getResult('SELECT * FROM '.sql_table('blog').' WHERE bshortname='. DB::quoteValue($name)); + return ($r->rowCount() != 0); + } + + /** + * Checks if a blog with a given id exists + * Returns true if there is a blog with the given ID (static) + * + * @param integer $id ID for searched weblog + * @return boolean exists or not + */ + public function existsID($id) + { + $r = DB::getResult('SELECT * FROM '.sql_table('blog').' WHERE bnumber='.intval($id)); + return ($r->rowCount() != 0); + } + + /** + * Blog::setFuturePost() + * flag there is a future post pending + * + * @param void + * @return void + */ + public function setFuturePost() + { + $query = "UPDATE %s SET bfuturepost='1' WHERE bnumber=%d;"; + $query = sprintf($query, sql_table('blog'), (integer) $this->blogid); + DB::execute($query); + return; + } + + /** + * Blog::clearFuturePost() + * clear there is a future post pending + * + * @param void + * @return void + */ + public function clearFuturePost() + { + $query = "UPDATE %s SET bfuturepost='0' WHERE bnumber=%d;"; + $query = sprintf($query, sql_table('blog'), (integer) $this->blogid); + DB::execute($query); + return; + } + + /** + * Blog::checkJustPosted() + * check if we should throw justPosted event + * + * @param void + * @return void + */ + public function checkJustPosted() + { + global $manager; + + if ( $this->settings['bfuturepost'] == 1 ) + { + $query = "SELECT * FROM %s WHERE iposted=0 AND iblog=%d AND itime < NOW();"; + $query = sprintf($query, sql_table('item'), (integer) $this->blogid); + + $result = DB::getResult($query); + if ( $result->rowCount() > 0 ) + { + // This $pinged is allow a plugin to tell other hook to the event that a ping is sent already + // Note that the plugins's calling order is subject to thri order in the plugin list + $pinged = FALSE; + $manager->notify('JustPosted', array('blogid' => $this->blogid, 'pinged' => &$pinged)); + + // clear all expired future posts + $query = "UPDATE %s SET iposted='1' WHERE iblog=%d AND itime < NOW();"; + $query = spriintf($query, sql_table('item'), (integer) $this->blogid); + DB::execute($query); + + // check to see any pending future post, clear the flag is none + $query = "SELECT * FROM %s WHERE iposted=0 AND iblog=%d;"; + $query = sprintf($query, sql_table('item'), (integer) $this->blogid); + + $result = DB::getResult($query); + if ( $result->rowCount() == 0 ) + { + $this->clearFuturePost(); + } + } + } + return; + } + + /** + * Blog::readLogFromList() + * Shows the given list of items for this blog + * + * @param array $itemarray array of item numbers to be displayed + * @param string $template string representing the template _NAME_ (!) + * @param string $highlight contains a query that should be highlighted + * @param boolean $comments 1=show comments 0=don't show comments + * @param boolean $dateheads 1=show dateheads 0=don't show dateheads + * @param boolean $showDrafts 0=do not show drafts 1=show drafts + * @param boolean $showFuture 0=do not show future posts 1=show future posts + * @return integer amount of items shown + */ + public function readLogFromList($itemarray, $template, $highlight = '', $comments = 1, $dateheads = 1,$showDrafts = 0, $showFuture = 0) + { + $query = $this->getSqlItemList($itemarray,$showDrafts,$showFuture); + return $this->showUsingQuery($template, $query, $highlight, $comments, $dateheads); + } + + /** + * Blog::getSqlItemList() + * Returns the SQL query used to fill out templates for a list of items + * No LIMIT clause is added. (caller should add this if multiple pages are requested) + * + * @param array $itemarray an array holding the item numbers of the items to be displayed + * @param integer $showDrafts 0=do not show drafts 1=show drafts + * @param integer $showFuture 0=do not show future posts 1=show future posts + * @return string either a full SQL query, or an empty string + */ + public function getSqlItemList($itemarray,$showDrafts = 0,$showFuture = 0) + { + if ( !is_array($itemarray) ) + { + return ''; + } + + $showDrafts = intval($showDrafts); + $showFuture = intval($showFuture); + $items = array(); + + foreach ( $itemarray as $value ) + { + if ( intval($value) ) + { + $items[] = intval($value); + } + } + if ( !count($items) ) + { + return ''; + } + + $i = count($items); + $query = ''; + foreach ( $items as $value ) + { + $query .= '(' + . 'SELECT' + . ' i.inumber as itemid,' + . ' i.ititle as title,' + . ' i.ibody as body,' + . ' m.mname as author,' + . ' m.mrealname as authorname,' + . ' i.itime,' + . ' i.imore as more,' + . ' m.mnumber as authorid,' + . ' m.memail as authormail,' + . ' m.murl as authorurl,' + . ' c.cname as category,' + . ' i.icat as catid,' + . ' i.iclosed as closed'; + + $query .= ' FROM ' + . sql_table('item') . ' as i, ' + . sql_table('member') . ' as m, ' + . sql_table('category') . ' as c' + . ' WHERE' + . ' i.iblog='.$this->blogid + . ' and i.iauthor=m.mnumber' + . ' and i.icat=c.catid'; + + // exclude drafts + if ( !$showDrafts ) + { + $query .= ' and i.idraft=0'; + } + if ( !$showFuture ) + { + // don't show future items + $query .= ' and i.itime<=' . DB::formatDateTime($this->getCorrectTime()); + } + + $query .= ' and i.inumber='.intval($value); + $query .= ')'; + $i--; + if ($i) $query .= ' UNION '; + } + + return $query; + } + + /** + * Blog::convertBreaks() + * Get the the setting for the line break handling + * [should be named as getConvertBreaks()] + * + * @deprecated + * @param void + * @return + */ + public function convertBreaks() + { + return $this->getSetting('bconvertbreaks'); + } + + /** + * Set the the setting for the line break handling + * + * @deprecated + * @param boolean $val new value for bconvertbreaks + * @return void + */ + public function setConvertBreaks($val) + { + $this->setSetting('bconvertbreaks', $val); + return; + } +} ++======= + blogid = (integer) $id; + $this->readSettings(); + $this->setSelectedCategory($catid); + return; + } + + /** + * Blog::readLog() + * Shows the given amount of items for this blog + * + * @param string $template String representing the template _NAME_ (!) + * @param integer $amountEntries amount of entries to show + * @param integer $startpos offset from where items should be shown (e.g. 5 = start at fifth item) + * @return integer amount of items shown + */ + public function readLog($template, $amountEntries, $offset = 0, $startpos = 0) + { + return $this->readLogAmount($template,$amountEntries,'','',1,1,$offset, $startpos); + } + + /** + * Blog::showArchive() + * Shows an archive for a given month + * + * @param integer $year year + * @param integer $month month + * @param string $template String representing the template name to be used + * @return void + */ + public function showArchive($templatename, $year, $month=0, $day=0) + { + // create extra where clause for select query + if ( $day == 0 && $month != 0 ) + { + $timestamp_start = mktime(0,0,0,$month,1,$year); + // also works when $month==12 + $timestamp_end = mktime(0,0,0,$month+1,1,$year); + } + elseif ( $month == 0 ) + { + $timestamp_start = mktime(0,0,0,1,1,$year); + // also works when $month==12 + $timestamp_end = mktime(0,0,0,12,31,$year); + } + else + { + $timestamp_start = mktime(0,0,0,$month,$day,$year); + $timestamp_end = mktime(0,0,0,$month,$day+1,$year); + } + $extra_query = " and i.itime>=%s and i.itime<%s"; + $extra_query = sprintf($extra_query, DB::formatDateTime($timestamp_start), DB::formatDateTime($timestamp_end)); + + $this->readLogAmount($templatename,0,$extra_query,'',1,1); + return; + } + + /** + * Blog::setSelectedCategory() + * Sets the selected category by id (only when category exists) + * + * @param integer $catid ID for category + * @return void + */ + public function setSelectedCategory($catid) + { + if ( $this->isValidCategory($catid) || (intval($catid) == 0) ) + { + $this->selectedcatid = intval($catid); + } + return; + } + + /** + * Blog::setSelectedCategoryByName() + * Sets the selected category by name + * + * @param string $catname name of category + * @return void + */ + public function setSelectedCategoryByName($catname) + { + $this->setSelectedCategory($this->getCategoryIdFromName($catname)); + return; + } + + /** + * Blog::getSelectedCategory() + * Returns the selected category + * + * @param void + * @return integer + */ + public function getSelectedCategory() + { + return $this->selectedcatid; + } + + /** + * Shows the given amount of items for this blog + * + * @param string $template string representing the template _NAME_ (!) + * @param integer $amountEntries amount of entries to show (0 = no limit) + * @param string $extraQuery extra conditions to be added to the query + * @param string $highlight contains a query that should be highlighted + * @param integer $comments 1=show comments 0=don't show comments + * @param integer $dateheads 1=show dateheads 0=don't show dateheads + * @param integer $offset offset + * @return integer amount of items shown + */ + private function readLogAmount($template, $amountEntries, $extraQuery, $highlight, $comments, $dateheads, $offset = 0, $startpos = 0) + { + $query = $this->getSqlBlog($extraQuery); + + if ( $amountEntries > 0 ) + { + // $offset zou moeten worden: + // (($startpos / $amountentries) + 1) * $offset ... later testen ... + $query .= ' LIMIT ' . intval($startpos + $offset).',' . intval($amountEntries); + } + return $this->showUsingQuery($template, $query, $highlight, $comments, $dateheads); + } + + /** + * Blog::showUsingQuery() + * Do the job for readLogAmmount + * + * @param string $templateName template name + * @param string $query string for query + * @param string $highlight string to be highlighted + * @param integer $comments the number of comments + * @param boolean $dateheads date header is needed or not + * @return integer the number of rows as a result of mysql query + */ + private function showUsingQuery($templateName, $query, $highlight = '', $comments = 0, $dateheads = 1) + { + global $CONF, $manager, $currentTemplateName; + + $lastVisit = cookieVar($CONF['CookiePrefix'] .'lastVisit'); + if ( $lastVisit != 0 ) + { + $lastVisit = $this->getCorrectTime($lastVisit); + } + + // set templatename as global variable (so plugins can access it) + $currentTemplateName = $templateName; + $template =& $manager->getTemplate($templateName); + + // create parser object & action handler + $handler = new ItemActions($this); + $handler->setTemplate($template); + $handler->setHighlight($highlight); + $handler->setLastVisit($lastVisit); + $handler->setShowComments($comments); + + $parser = new Parser($handler); + + // execute query + $items = DB::getResult($query); + + // loop over all items + $old_date = 0; + foreach ( $items as $item ) + { + // string timestamp -> unix timestamp + $item['timestamp'] = strtotime($item['itime']); + + // action handler needs to know the item we're handling + $handler->setCurrentItem($item); + + // add date header if needed + if ( $dateheads ) + { + $new_date = date('dFY', $item['timestamp']); + if ( $new_date != $old_date ) + { + // unless this is the first time, write date footer + $timestamp = $item['timestamp']; + if ( $old_date != 0 ) + { + $oldTS = strtotime($old_date); + $data = array('blog' => &$this, 'timestamp' => $oldTS); + $manager->notify('PreDateFoot', $data); + + if ( !in_array('DATE_FOOTER', $template) || empty($template['DATE_FOOTER']) ) + { + $tmp_footer = ''; + } + else + { + $tmp_footer = i18n::formatted_datetime($template['DATE_FOOTER'], $oldTS); + } + $parser->parse($tmp_footer); + $manager->notify('PostDateFoot', $data); + } + + $data = array('blog' => &$this, 'timestamp' => $timestamp); + $manager->notify('PreDateHead', $data); + + // note, to use templatvars in the dateheader, the %-characters need to be doubled in + // order to be preserved by strftime + if ( !in_array('DATE_HEADER', $template) || empty($template['DATE_HEADER']) ) + { + $tmp_header = ''; + } + else + { + $tmp_header = i18n::formatted_datetime($template['DATE_HEADER'], $timestamp); + } + $parser->parse($tmp_header); + $manager->notify('PostDateHead', $data); + } + $old_date = $new_date; + } + + // parse item + $parser->parse($template['ITEM_HEADER']); + $data = array('blog' => &$this, 'item' => &$item); + $manager->notify('PreItem', $data); + $parser->parse($template['ITEM']); + $manager->notify('PostItem', $data); + $parser->parse($template['ITEM_FOOTER']); + } + + $numrows = $items->rowCount(); + + // add another date footer if there was at least one item + if ( ($numrows > 0) && $dateheads ) + { + $data = array('blog' => &$this, 'timestamp' => strtotime($old_date)); + $manager->notify('PreDateFoot', $data); + $parser->parse($template['DATE_FOOTER']); + $manager->notify('PostDateFoot', $data); + } + + $items->closeCursor(); + return $numrows; + } + + /** + * Blog::showOneitem() + * Simplified function for showing only one item + * + * @param integer $itemid ID for item + * @param array $template template for item + * @param string $highlight string for highlight + * @return integer 1 + */ + public function showOneitem($itemid, $template, $highlight) + { + $extraQuery = ' and inumber=' . intval($itemid); + + return $this->readLogAmount($template, 1, $extraQuery, $highlight, 0, 0); + } + + /** + * Blog::addItem() + * Adds an item to this blog + * + * @param integer $catid ID for category + * @param string $title ID for + * @param string $body text for body + * @param string $more text for more + * @param integer $blogid ID for blog + * @param integer $authorid ID for author + * @param timestamp $timestamp UNIX timestamp for post + * @param boolean $closed opened or closed + * @param boolean $draft draft or not + * @param boolean $posted posted or not + * @return integer ID for added item + */ + function additem($catid, $title, $body, $more, $blogid, $authorid, $timestamp, $closed, $draft, $posted='1') + { + global $manager; + + $blogid = (integer) $blogid; + $authorid = (integer) $authorid; + $title = $title; + $body = $body; + $more = $more; + $catid = intval($catid); + + // convert newlines to
+ if ( $this->convertBreaks() ) + { + $body = addBreaks($body); + $more = addBreaks($more); + } + + if ( $closed != '1' ) + { + $closed = '0'; + } + if ( $draft != '0' ) + { + $draft = '1'; + } + + if ( !$this->isValidCategory($catid) ) + { + $catid = $this->getDefaultCategory(); + } + + $isFuture = 0; + if ( $timestamp > $this->getCorrectTime() ) + { + $isFuture = 1; + } + + $timestamp = date('Y-m-d H:i:s',$timestamp); + + $data = array('title' => &$title, 'body' => &$body, 'more' => &$more, 'blog' => $this, 'authorid' => &$authorid, 'timestamp' => &$timestamp, 'closed' => &$closed, 'draft' => &$draft, 'catid' => &$catid); + $manager->notify('PreAddItem', $data); + + $ititle = DB::quoteValue($title); + $ibody = DB::quoteValue($body); + $imore = DB::quoteValue($more); + $timestamp = DB::formatDateTime(strtotime($timestamp)); + + $query = "INSERT INTO %s (ITITLE, IBODY, IMORE, IBLOG, IAUTHOR, ITIME, ICLOSED, IDRAFT, ICAT, IPOSTED) VALUES (%s, %s, %s, %d, %d, %s, %s, %s, %s, %s)"; + $query = sprintf($query, sql_table('item'), $ititle, $ibody, $imore, $blogid, $authorid, $timestamp, $closed, $draft, $catid, $posted); + DB::execute($query); + $itemid = DB::getInsertId(); + + $data = array('itemid' => $itemid); + $manager->notify('PostAddItem', $data); + + if ( !$draft ) + { + $this->updateUpdateFile(); + } + // send notification mail + if ( !$draft && !$isFuture && $this->getNotifyAddress() && $this->notifyOnNewItem() ) + { + $this->sendNewItemNotification($itemid, $title, $body); + } + return $itemid; + } + + /** + * Blog::sendNewItemNotification() + * Send a new item notification to the notification list + * + * @param string $itemid ID of the item + * @param string $title title of the item + * @param string $body body of the item + * @return void + */ + public function sendNewItemNotification($itemid, $title, $body) + { + global $CONF, $member; + + $ascii = Entity::anchor_footnoting($body); + + $message = _NOTIFY_NI_MSG . " \n"; + $temp = parse_url($CONF['Self']); + if ( $temp['scheme'] ) + { + $message .= Link::create_item_link($itemid) . "\n\n"; + } + else + { + $tempurl = $this->getURL(); + if ( i18n::substr($tempurl, -1) == '/' || i18n::substr($tempurl, -4) == '.php' ) + { + $message .= $tempurl . '?itemid=' . $itemid . "\n\n"; + } + else + { + $message .= $tempurl . '/?itemid=' . $itemid . "\n\n"; + } + } + $message .= _NOTIFY_TITLE . ' ' . strip_tags($title) . "\n"; + $message .= _NOTIFY_CONTENTS . "\n " . $ascii . "\n"; + $message .= NOTIFICATION::get_mail_footer(); + + $subject = $this->getName() . ': ' . _NOTIFY_NI_TITLE; + + $from = $member->getNotifyFromMailAddress(); + + NOTIFICATION::mail($this->getNotifyAddress(), $subject, $message, $from, i18n::get_current_charset()); + return; + } + + /** + * Blog::createNewCategory() + * Creates a new category for this blog + * + * @param string $catName name of the new category. When empty, a name is generated automatically (starting with newcat) + * @param string $catDescription description of the new category. Defaults to 'New Category' + * @return integer ID for new category on success. 0 on failure + */ + public function createNewCategory($catName = '', $catDescription = _CREATED_NEW_CATEGORY_DESC) + { + global $member, $manager; + + if ( !$member->blogAdminRights($this->blogid) ) + { + return 0; + } + + // generate + if ( $catName == '' ) + { + $catName = _CREATED_NEW_CATEGORY_NAME; + $i = 1; + + $res = DB::getResult('SELECT * FROM '.sql_table('category')." WHERE cname='".$catName.$i."' and cblog=".$this->blogid); + while ( $res->rowCount() > 0 ) + { + $i++; + $res = DB::getResult('SELECT * FROM '.sql_table('category')." WHERE cname='".$catName.$i."' and cblog=".$this->blogid); + } + + $catName = $catName . $i; + } + + $data = array( + 'blog' => &$this, + 'name' => &$catName, + 'description' => $catDescription + ); + $manager->notify('PreAddCategory', $data); + + $query = "INSERT INTO %s (cblog, cname, cdesc) VALUES (%d, %s, %s)"; + $query = sprintf($query, sql_table('category'), (integer) $this->blogid, DB::quoteValue($catName), DB::quoteValue($catDescription)); + DB::execute($query); + $catid = DB::getInsertId(); + + $data = array( + 'blog' => &$this, + 'name' => $catName, + 'description' => $catDescription, + 'catid' => $catid + ); + $manager->notify('PostAddCategory', $data); + + return $catid; + } + + /** + * Blog::search() + * Searches all months of this blog for the given query + * + * @param string $query search query + * @param array $template template to be used (__NAME__ of the template) + * @param integer $amountMonths max amount of months to be search (0 = all) + * @param integer $maxresults max number of results to show + * @param integer $startpos offset + * @return amount of hits found + */ + public function search($query, $template, $amountMonths, $maxresults, $startpos) { + global $CONF, $manager; + + $highlight = ''; + $sqlquery = $this->getSqlSearch($query, $amountMonths, $highlight); + + if ( $sqlquery == '' ) + { + // no query -> show everything + $extraquery = ''; + $amountfound = $this->readLogAmount($template, $maxresults, $extraQuery, $query, 1, 1); + } + else + { + // add LIMIT to query (to split search results into pages) + if ( intval($maxresults > 0) ) + { + $sqlquery .= ' LIMIT ' . intval($startpos) . ',' . intval($maxresults); + } + + // show results + $amountfound = $this->showUsingQuery($template, $sqlquery, $highlight, 1, 1); + + // when no results were found, show a message + if ( $amountfound == 0 ) + { + $template =& $manager->getTemplate($template); + $vars = array( + 'query' => Entity::hsc($query), + 'blogid' => $this->blogid + ); + echo Template::fill($template['SEARCH_NOTHINGFOUND'], $vars); + } + } + return $amountfound; + } + + /** + * Blog::getSqlSearch() + * Returns an SQL query to use for a search query + * No LIMIT clause is added. (caller should add this if multiple pages are requested) + * + * @param string $query search query + * @param integer $amountMonths amount of months to search back. Default = 0 = unlimited + * @param string $mode either empty, or 'count'. In this case, the query will be a SELECT COUNT(*) query + * @return string $highlight words to highlight (out parameter) + * @return string either a full SQL query, or an empty string (if querystring empty) + */ + public function getSqlSearch($query, $amountMonths = 0, &$highlight, $mode = '') + { + $searchclass = new Search($query); + + $highlight = $searchclass->inclusive; + + // if querystring is empty, return empty string + if ( $searchclass->inclusive == '' ) + { + return ''; + } + + $where = $searchclass->boolean_sql_where('ititle,ibody,imore'); + $select = $searchclass->boolean_sql_select('ititle,ibody,imore'); + + // get list of blogs to search + $blogs = $searchclass->blogs; // array containing blogs that always need to be included + $blogs[] = $this->blogid; // also search current blog (duh) + $blogs = array_unique($blogs); // remove duplicates + $selectblogs = ''; + if ( count($blogs) > 0 ) + { + $selectblogs = ' and i.iblog in (' . implode(',', $blogs) . ')'; + } + + if ( $mode == '' ) + { + $query = 'SELECT i.inumber as itemid, i.ititle as title, i.ibody as body, i.itime, i.imore as more, i.icat as catid, i.iclosed as closed, + m.mname as author, m.mrealname as authorname, m.mnumber as authorid, m.memail as authormail, m.murl as authorurl, + c.cname as category'; + + if ( $select ) + { + $query .= ', '.$select. ' as score '; + } + } + else + { + $query = 'SELECT COUNT(*) as result '; + } + + $query .= ' FROM '.sql_table('item').' as i, '.sql_table('member').' as m, '.sql_table('category').' as c' + . ' WHERE i.iauthor=m.mnumber' + . ' and i.icat=c.catid' + // exclude drafts + . ' and i.idraft=0' + . $selectblogs + // don't show future items + . ' and i.itime<=' . DB::formatDateTime($this->getCorrectTime()) + . ' and '.$where; + + // take into account amount of months to search + if ( $amountMonths > 0 ) + { + $localtime = getdate($this->getCorrectTime()); + $timestamp_start = mktime(0,0,0,$localtime['mon'] - $amountMonths,1,$localtime['year']); + $query .= ' and i.itime>' . DB::formatDateTime($timestamp_start); + } + + if ( $mode == '' ) + { + if ( $select ) + { + $query .= ' ORDER BY score DESC'; + } + else + { + $query .= ' ORDER BY i.itime DESC '; + } + } + + return $query; + } + + /** + * Blog::getSqlBlog() + * Returns the SQL query that's normally used to display the blog items on the index type skins + * No LIMIT clause is added. (caller should add this if multiple pages are requested) + * + * @param string $extraQuery extra query string + * @param string $mode either empty, or 'count'. In this case, the query will be a SELECT COUNT(*) query + * @return string either a full SQL query, or an empty string + */ + public function getSqlBlog($extraQuery, $mode = '') + { + if ( $mode == '' ) + { + $query = 'SELECT i.inumber as itemid, i.ititle as title, i.ibody as body, m.mname as author, + m.mrealname as authorname, i.itime, i.imore as more, m.mnumber as authorid, m.memail as authormail, + m.murl as authorurl, c.cname as category, i.icat as catid, i.iclosed as closed'; + } + else + { + $query = 'SELECT COUNT(*) as result '; + } + + $query .= ' FROM '.sql_table('item').' as i, '.sql_table('member').' as m, '.sql_table('category').' as c' + . ' WHERE i.iblog='.$this->blogid + . ' and i.iauthor=m.mnumber' + . ' and i.icat=c.catid' + . ' and i.idraft=0' // exclude drafts + . ' and i.itime<=' . DB::formatDateTime($this->getCorrectTime()); // don't show future items + + if ( $this->selectedcatid ) + { + $query .= ' and i.icat=' . $this->selectedcatid . ' '; + } + + $query .= $extraQuery; + + if ( $mode == '' ) + { + $query .= ' ORDER BY i.itime DESC'; + } + return $query; + } + + /** + * Blog::showArchiveList() + * Shows the archivelist using the given template + * + * @param string $template template name + * @param string $mode year/month/day + * @param integer $limit limit of record count + * @return void + */ + public function showArchiveList($template, $mode = 'month', $limit = 0) + { + global $CONF, $catid, $manager; + + if ( !isset ($linkparams) ) + { + $linkparams = array(); + } + + if ( $catid ) + { + $linkparams = array('catid' => $catid); + } + + $template =& $manager->getTemplate($template); + $listitem['blogid'] = $this->blogid; + + if ( !array_key_exists('ARCHIVELIST_HEADER', $template) || !$template['ARCHIVELIST_HEADER'] ) + { + $tplt = ''; + } + else + { + $tplt = $template['ARCHIVELIST_HEADER']; + } + + echo Template::fill($tplt, $listitem); + + $query = 'SELECT itime, SUBSTRING(itime,1,4) AS Year, SUBSTRING(itime,6,2) AS Month, SUBSTRING(itime,9,2) AS Day' + . ' FROM '.sql_table('item') + . ' WHERE iblog=' . $this->blogid + . ' AND itime <=' . DB::formatDateTime($this->getCorrectTime()) // don't show future items! + . ' AND idraft=0'; // don't show draft items + + if ( $catid ) + { + $query .= ' and icat=' . intval($catid); + } + + $query .= ' GROUP BY Year'; + if ( $mode == 'month' || $mode == 'day' ) + { + $query .= ', Month'; + } + if ( $mode == 'day' ) + { + $query .= ', Day'; + } + + $query .= ' ORDER BY itime DESC'; + + if ( $limit > 0 ) + { + $query .= ' LIMIT ' . intval($limit); + } + + $res = DB::getResult($query); + foreach ( $res as $current ) + { + /* string time -> unix timestamp */ + $current['itime'] = strtotime($current['itime']); + + if ( $mode == 'day' ) + { + $archivedate = date('Y-m-d',$current['itime']); + $archive['day'] = date('d',$current['itime']); + $listitem['day'] = date('d',$current['itime']); + $listitem['month'] = date('m',$current['itime']); + $archive['month'] = $listitem['month']; + } + elseif ( $mode == 'year' ) + { + $archivedate = date('Y',$current['itime']); + $listitem['day'] = ''; + $listitem['month'] = ''; + $archive['day'] = ''; + $archive['month'] = ''; + } + else + { + $archivedate = date('Y-m',$current['itime']); + $listitem['month'] = date('m',$current['itime']); + $archive['month'] = $listitem['month']; + $listitem['day'] = ''; + $archive['day'] = ''; + } + + $listitem['year'] = date('Y',$current['itime']); + $archive['year'] = $listitem['year']; + $listitem['archivelink'] = Link::create_archive_link($this->blogid,$archivedate,$linkparams); + + $data = array('listitem' => &$listitem); + $manager->notify('PreArchiveListItem', $data); + + $temp = Template::fill($template['ARCHIVELIST_LISTITEM'],$listitem); + echo i18n::formatted_datetime($temp, $current['itime']); + return; + } + + $res->closeCursor(); + + if ( !array_key_exists('ARCHIVELIST_FOOTER', $template) || !$template['ARCHIVELIST_FOOTER'] ) + { + $tplt = ''; + } + else + { + $tplt = $template['ARCHIVELIST_FOOTER']; + } + + echo Template::fill($tplt, $listitem); + return; + } + + /** + * Blog::showCategoryList() + * Shows the list of categories using a given template + * + * @param string $template Template Name + * @return void + */ + public function showCategoryList($template) + { + global $CONF, $archive, $archivelist, $manager; + + /* + * determine arguments next to catids + * I guess this can be done in a better way, but it works + */ + $linkparams = array(); + if ( $archive ) + { + $blogurl = Link::create_archive_link($this->blogid, $archive, ''); + $linkparams['blogid'] = $this->blogid; + $linkparams['archive'] = $archive; + } + else if ( $archivelist ) + { + $blogurl = Link::create_archivelist_link($this->blogid, ''); + $linkparams['archivelist'] = $archivelist; + } + else + { + $blogurl = Link::create_blogid_link($this->blogid, ''); + $linkparams['blogid'] = $this->blogid; + } + + $template =& $manager->getTemplate($template); + + //: Change: Set nocatselected variable + if ( $this->selectedcatid ) + { + $nocatselected = 'no'; + } + else + { + $nocatselected = 'yes'; + } + + $args = array( + 'blogid' => $this->blogid, + 'blogurl' => $blogurl, + 'self' => $CONF['Self'], + 'catiscurrent' => $nocatselected, // Change: Set catiscurrent template variable for header + 'currentcat' => $nocatselected + ); + + /* output header of category list item */ + if ( !array_key_exists('CATLIST_HEADER', $template) || empty($template['CATLIST_HEADER']) ) + { + echo Template::fill(NULL, $args); + } + else + { + echo Template::fill($template['CATLIST_HEADER'], $args); + } + + $query = "SELECT catid, cdesc as catdesc, cname as catname FROM %s WHERE cblog=%d ORDER BY cname ASC;"; + $query = sprintf($query, sql_table('category'), (integer) $this->blogid); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $args = array( + 'catid' => $row['catid'], + 'name' => $row['catname'], + 'extra' => $linkparams + ); + + $row['blogid'] = $this->blogid; + $row['blogurl'] = $blogurl; + $row['catlink'] = Link::create_link('category', $args); + $row['self'] = $CONF['Self']; + + // this gives catiscurrent = no when no category is selected. + $row['catiscurrent'] = 'no'; + $row['currentcat'] = 'no'; + + if ( $this->selectedcatid ) + { + if ( $this->selectedcatid == $row['catid'] ) + { + $row['catiscurrent'] = 'yes'; + $row['currentcat'] = 'yes'; + } + } + else + { + global $itemid; + if ( (integer) $itemid && $manager->existsItem((integer) $itemid, 0, 0) ) + { + $iobj =& $manager->getItem($itemid, 0, 0); + $cid = $iobj['catid']; + + if ( $cid == $row['catid'] ) + { + $row['catiscurrent'] = 'yes'; + $row['currentcat'] = 'yes'; + } + } + } + + $data = array('listitem' => &$row); + $manager->notify('PreCategoryListItem', $data); + + if ( !array_key_exists('CATLIST_LISTITEM', $template) || empty($template['CATLIST_LISTITEM'])) + { + echo Template::fill(NULL, $row); + } + else + { + echo Template::fill($template['CATLIST_LISTITEM'], $row); + } + } + + $res->closeCursor(); + + $args = array( + 'blogid' => $this->blogid, + 'blogurl' => $blogurl, + 'self' => $CONF['Self'], + 'catiscurrent' => $nocatselected, //: Change: Set catiscurrent template variable for footer + 'currentcat' => $nocatselected + ); + + if ( !array_key_exists('CATLIST_FOOTER', $template) || empty($template['CATLIST_FOOTER'])) + { + echo Template::fill(NULL, $args); + } + else + { + echo Template::fill($template['CATLIST_FOOTER'], $args); + } + + return; + } + + /** + * Blog::showBlogList() + * Shows a list of all blogs in the system using a given template + * ordered by number, name, shortname or description + * in ascending or descending order + * + * @param string $template tempalte name + * @param string $bnametype bname/bshortname + * @param string $orderby string for 'ORDER BY' SQL + * @param string $direction ASC/DESC + * @return void + */ + static public function showBlogList($template, $bnametype, $orderby, $direction) + { + global $CONF, $manager; + + switch ( $orderby ) + { + case 'number': + $orderby='bnumber'; + break; + case 'name': + $orderby='bname'; + break; + case 'shortname': + $orderby='bshortname'; + break; + case 'description': + $orderby='bdesc'; + break; + default: + $orderby='bnumber'; + break; + } + + $direction=strtolower($direction); + switch ( $direction ) + { + case 'asc': + $direction='ASC'; + break; + case 'desc': + $direction='DESC'; + break; + default: + $direction='ASC'; + break; + } + + $template =& $manager->getTemplate($template); + + if ( array_key_exists('BLOGLIST_HEADER', $template) && !empty($template['BLOGLIST_HEADER']) ) + { + $vars = array( + 'sitename' => $CONF['SiteName'], + 'siteurl' => $CONF['IndexURL'] + ); + + echo Template::fill($template['BLOGLIST_HEADER'], $vars); + } + + if ( array_key_exists('BLOGLIST_LISTITEM', $template) && !empty($template['BLOGLIST_LISTITEM']) ) + { + $query = 'SELECT bnumber, bname, bshortname, bdesc, burl FROM '.sql_table('blog').' ORDER BY '.$orderby.' '.$direction; + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $list = array(); + $list['bloglink'] = Link::create_blogid_link($row['bnumber']); + $list['blogdesc'] = $row['bdesc']; + $list['blogurl'] = $row['burl']; + + if ( $bnametype == 'shortname' ) + { + $list['blogname'] = $row['bshortname']; + } + else + { + /* all other cases */ + $list['blogname'] = $row['bname']; + } + + $data = array('listitem' => &$list); + $manager->notify('PreBlogListItem', $data); + + echo Template::fill($template['BLOGLIST_LISTITEM'], $list); + } + + $res->closeCursor(); + } + + + if ( array_key_exists('BLOGLIST_FOOTER', $template) && !empty($template['BLOGLIST_FOOTER']) ) + { + $vars = array( + 'sitename' => $CONF['SiteName'], + 'siteurl' => $CONF['IndexURL'] + ); + echo Template::fill($template['BLOGLIST_FOOTER']); + } + return; + } + + /** + * Blog::readSettings() + * Read the blog settings + * + * @param void + * @return void + */ + public function readSettings() + { + $query = 'SELECT * FROM %s WHERE bnumber=%d;'; + $query = sprintf($query, sql_table('blog'), (integer) $this->blogid); + $res = DB::getResult($query); + + $this->isValid = ($res->rowCount() > 0); + if ( $this->isValid ) + { + $this->settings = $res->fetch(PDO::FETCH_ASSOC); + } + return; + } + + /** + * Blog::writeSettings() + * Write the blog settings + */ + public function writeSettings() + { + // (can't use floatval since not available prior to PHP 4.2) + $offset = $this->getTimeOffset(); + if ( !is_float($offset) ) + { + $offset = (integer) $offset; + } + + $query = 'UPDATE '.sql_table('blog') + . ' SET bname=' . DB::quoteValue($this->getName()) . ',' + . ' bshortname='. DB::quoteValue($this->getShortName()) . ',' + . ' bcomments='. intval($this->commentsEnabled()) . ',' + . ' bmaxcomments=' . intval($this->getMaxComments()) . ',' + . ' btimeoffset=' . $offset . ',' + . ' bpublic=' . intval($this->isPublic()) . ',' + . ' breqemail=' . intval($this->emailRequired()) . ',' + . ' bconvertbreaks=' . intval($this->convertBreaks()) . ',' + . ' ballowpast=' . intval($this->allowPastPosting()) . ',' + . ' bnotify=' . DB::quoteValue($this->getNotifyAddress()) . ',' + . ' bnotifytype=' . intval($this->getNotifyType()) . ',' + . ' burl=' . DB::quoteValue($this->getURL()) . ',' + . ' bupdate=' . DB::quoteValue($this->getUpdateFile()) . ',' + . ' bdesc=' . DB::quoteValue($this->getDescription()) . ',' + . ' bdefcat=' . intval($this->getDefaultCategory()) . ',' + . ' bdefskin=' . intval($this->getDefaultSkin()) . ',' + . ' bincludesearch=' . intval($this->getSearchable()) + . ' WHERE bnumber=' . intval($this->blogid); + DB::execute($query); + return; + } + + /** + * Blog::updateUpdatefile() + * Update the update file if requested + * + * @param void + * @return void + */ + public function updateUpdatefile() + { + if ( $this->getUpdateFile() ) + { + $f_update = fopen($this->getUpdateFile(), 'w'); + fputs($f_update,$this->getCorrectTime()); + fclose($f_update); + } + return; + } + + /** + * Blog::isValidCategory() + * Check if a category with a given catid is valid + * + * @param integer $catid ID for category + * @return boolean exists or not + */ + public function isValidCategory($catid) + { + $query = 'SELECT * FROM %s WHERE cblog=%d and catid=%d;'; + $query = sprintf($query, sql_table('category'), (integer) $this->blogid, (integer) $catid); + $res = DB::getResult($query); + return ($res->rowCount() != 0); + } + + /** + * Blog::getCategoryName() + * Get the category name for a given catid + * + * @param integer $catid ID for category + * @return string name of category + */ + public function getCategoryName($catid) + { + $query = 'SELECT cname FROM %s WHERE cblog=%d and catid=%d;'; + $query = sprintf($query, sql_table('category'), (integer) $this->blogid, (integer) $catid); + $res = DB::getValue($query); + return $res; + } + + /** + * Blog::getCategoryDesc() + * Get the category description for a given catid + * + * @param $catid + * category id + */ + public function getCategoryDesc($catid) + { + $query = 'SELECT cdesc FROM %s WHERE cblog=%d and catid=%d;'; + $query = sprintf($query, sql_table('category'), (integer) $this->blogid, (integer) $catid); + $res = DB::getValue($query); + return $res; + } + + /** + * Blog::getCategoryIdFromName + * Get the category id for a given category name + * + * @param string $name category name + * @return ID for category + */ + public function getCategoryIdFromName($name) + { + $query = 'SELECT catid FROM %s WHERE cblog=%d and cname=%s;'; + $query = sprintf($query, sql_table('category'), (integer) $this->blogid, DB::quoteValue($name)); + + $res = DB::getValue(); + if ( !$res ) + { + return $this->getDefaultCategory(); + } + return $res; + } + + /** + * Blog::insertJavaScriptInfo() + * Insert a javascript that includes information about the settings + * of an author: ConvertBreaks, MediaUrl and AuthorId + * + * @param $authorid id of the author + */ + public function insertJavaScriptInfo($authorid = '') + { + global $member, $CONF; + + if ( $authorid == '' ) + { + $authorid = $member->getID(); + } + + echo "\n"; + return; + } + + /** + * Blog::setAllowPastPosting() + * Set the the setting for allowing to publish postings in the past + * + * @param boolean $val new value for ballowpast + * @return void + */ + public function setAllowPastPosting($val) + { + $this->setSetting('ballowpast', $val); + return; + } + + /** + * Blog::allowPastPosting() + * Get the the setting if it is allowed to publish postings in the past + * [should be named as getAllowPastPosting()] + * + * @param void + * @return boolean + */ + public function allowPastPosting() + { + return $this->getSetting('ballowpast'); + } + + /** + * Blog::getCorrectTime() + * + * @param integer $t + * @return integer + */ + public function getCorrectTime($t=0) + { + if ( $t == 0 ) + { + $t = time(); + } + return ($t + 3600 * $this->getTimeOffset()); + } + + /** + * Blog::getName() + * + * @param void + * @return string name of this weblog + */ + public function getName() + { + return $this->getSetting('bname'); + } + + /** + * Blog::getShortName() + * + * @param void + * @return string short name of this weblog + */ + public function getShortName() + { + return $this->getSetting('bshortname'); + } + + /** + * Blog::getMaxComments() + * + * @param void + * @return integer maximum number of comments + */ + public function getMaxComments() + { + return $this->getSetting('bmaxcomments'); + } + + /** + * Blog::getNotifyAddress() + * + * @param void + * @return string mail address for notifying + */ + public function getNotifyAddress() + { + return $this->getSetting('bnotify'); + } + + /** + * Blog::getNotifyType() + * + * @param void + * @return integer notifycation type + */ + public function getNotifyType() + { + return $this->getSetting('bnotifytype'); + } + + /** + * Blog::notifyOnComment() + * + * @param void + * @return boolean + */ + public function notifyOnComment() + { + $n = $this->getNotifyType(); + return (($n != 0) && (($n % 3) == 0)); + } + + /** + * Blog::notifyOnVote() + * + * @param void + * @return boolean + */ + public function notifyOnVote() + { + $n = $this->getNotifyType(); + return (($n != 0) && (($n % 5) == 0)); + } + + /** + * Blog::notifyOnNewItem() + * + * @param void + * @return boolean + */ + public function notifyOnNewItem() + { + $n = $this->getNotifyType(); + return (($n != 0) && (($n % 7) == 0)); + } + + /** + * Blog::setNotifyType() + * + * @param integer $val + * @return void + */ + public function setNotifyType($val) + { + $this->setSetting('bnotifytype',$val); + return; + } + + /** + * Blog::getTimeOffset() + * @param void + * @return + */ + public function getTimeOffset() + { + return $this->getSetting('btimeoffset'); + } + + /** + * Blog::commentsEnabled() + * @param void + * @return integer enabled or not + */ + public function commentsEnabled() + { + return $this->getSetting('bcomments'); + } + + /** + * Blog::getURL() + * @param void + * @return string URI for this weblog + */ + public function getURL() + { + return $this->getSetting('burl'); + } + + /** + * Blog::getDefaultSkin() + * @param void + * @return name of skin as default for this weblog + */ + public function getDefaultSkin() + { + return $this->getSetting('bdefskin'); + } + + /** + * Blog::getUpdateFile() + * @param void + * @return string name of file to be updated when weblog is updated + */ + public function getUpdateFile() + { + return $this->getSetting('bupdate'); + } + + /** + * Blog::getDescription() + * @param void + * @return string description for this weblog + */ + public function getDescription() + { + return $this->getSetting('bdesc'); + } + + /** + * Blog::isPublic() + * @param void + * @return integer publlic or not + */ + public function isPublic() + { + return $this->getSetting('bpublic'); + } + + /** + * Blog::emailRequired() + * @param void + * @return integer email is required when posting comment or not + */ + public function emailRequired() + { + return $this->getSetting('breqemail'); + } + + /** + * Blog::getSearchable() + * @param void + * @return integer searchable or not + */ + public function getSearchable() + { + return $this->getSetting('bincludesearch'); + } + + /** + * Blog::getDefaultCategory() + * @param void + * @return ID for category as a default + */ + public function getDefaultCategory() + { + return $this->getSetting('bdefcat'); + } + + /** + * Blog::setPublic() + * @param integer $val allow comments by non-registered members or not + * @return void + */ + public function setPublic($val) + { + $this->setSetting('bpublic', $val); + return; + } + + /** + * Blog::setSearchable() + * @param integer $val searchable from the other blogs or not + * @return void + */ + public function setSearchable($val) + { + $this->setSetting('bincludesearch', $val); + return; + } + + /** + * Blog::setDescription + * @param string $val description for this weblog + * @return void + */ + public function setDescription($val) + { + $this->setSetting('bdesc',$val); + return; + } + + /** + * Blog::setUpdateFile() + * @param string $val name of file to beupdated when weblog is updated + * @return + */ + public function setUpdateFile($val) + { + $this->setSetting('bupdate',$val); + return; + } + + /** + * Blog::setDefaultSkin() + * @param integer $val ID for default skin to use when displaying this weblog + * @return void + */ + public function setDefaultSkin($val) + { + $this->setSetting('bdefskin', $val); + return; + } + + /** + * Blog::setURL() + * @param string $val URI for this weblog + * @return + */ + public function setURL($val) + { + $this->setSetting('burl', $val); + return; + } + + /** + * Blog::setName() + * @param string $val name of this weblog + * @return void + */ + public function setName($val) + { + $this->setSetting('bname', $val); + return; + } + + /** + * Blog::setShortName() + * @param string $val short name for this weblog + * @return void + */ + public function setShortName($val) + { + $this->setSetting('bshortname', $val); + return; + } + + /** + * Blog::setCommentsEnabled() + * @param integer $val enabling posting comment or not + * @return void + */ + public function setCommentsEnabled($val) + { + $this->setSetting('bcomments',$val); + return; + } + + /** + * Blog::setMaxComments() + * @param integer $val maximum number of comments for this weblog + * @return void + */ + public function setMaxComments($val) + { + $this->setSetting('bmaxcomments', $val); + return; + } + + /** + * Blog::setNotifyAddress() + * @param string $val email to be notified if weblog updated + * @return void + */ + public function setNotifyAddress($val) + { + $this->setSetting('bnotify', $val); + return; + } + + /** + * Blog::setEmailRequired() + * @param string requiring comments with email or not from non member + * @return void + */ + public function setEmailRequired($val) + { + $this->setSetting('breqemail', $val); + return; + } + + /** + * Blog::setTimeOffset() + * @param integer $val time offset + * @return void + */ + public function setTimeOffset($val) + { + // check validity of value + // 1. replace , by . (common mistake) + $val = str_replace(',','.',$val); + + // 2. cast to float or int + if ( is_numeric($val) && (i18n::strpos($val, '.5') === (i18n::strlen($val) - 2)) ) + { + $val = (float) $val; + } + else + { + $val = (integer) $val; + } + + $this->setSetting('btimeoffset',$val); + return; + } + + /** + * Blog::setDefaultCategory() + * @param integer $val ID for default category for this weblog + * @return + */ + public function setDefaultCategory($val) + { + $this->setSetting('bdefcat',$val); + return; + } + + /** + * Blog::getSetting() + * @param string $key key for setting of this weblog + * @return mixed value for the setting + */ + public function getSetting($key) + { + return $this->settings[$key]; + } + + /** + * Blog::setSetting() + * @param string $key key for setting of this weblog + * @param mixed $value value for the key + * @return + */ + public function setSetting($key, $value) + { + $this->settings[$key] = $value; + return; + } + + /** + * Blog::addTeamMember() + * Tries to add a member to the team. + * Returns false if the member was already on the team + * + * @param integer $memberid id for member + * @param boolean $admin super-admin or not + * @return boolean Success/Fail + */ + public function addTeamMember($memberid, $admin) + { + global $manager; + + $memberid = intval($memberid); + $admin = intval($admin); + + // check if member is already a member + $tmem =& $manager->getMember($memberid); + + if ( $tmem->isTeamMember($this->blogid) ) + { + return 0; + } + + $data = array( + 'blog' => &$this, + 'member' => &$tmem, + 'admin' => &$admin + ); + $manager->notify('PreAddTeamMember', $data); + + // add to team + $query = "INSERT INTO %s (TMEMBER, TBLOG, TADMIN) VALUES (%d, %d, %d);"; + $query = sprintf($query, sql_table('team'), (integer) $memberid, (integer) $this->blogid, (integer) $admin); + DB::execute($query); + + $data = array( + 'blog' => &$this, + 'member' => &$tmem, + 'admin' => $admin + ); + $manager->notify('PostAddTeamMember', $data); + + $logMsg = sprintf(_TEAM_ADD_NEWTEAMMEMBER, $tmem->getDisplayName(), $memberid, $this->getName()); + ActionLog::add(INFO, $logMsg); + + return 1; + } + + /** + * Blog::getID() + * @param void + * @return integer ID for this weblog + */ + public function getID() + { + return (integer) $this->blogid; + } + + /** + * Checks if a blog with a given shortname exists + * Returns true if there is a blog with the given shortname (static) + * + * @param string $name blog shortname + * @return boolean exists or not + */ + public function exists($name) + { + $r = DB::getResult('SELECT * FROM '.sql_table('blog').' WHERE bshortname='. DB::quoteValue($name)); + return ($r->rowCount() != 0); + } + + /** + * Checks if a blog with a given id exists + * Returns true if there is a blog with the given ID (static) + * + * @param integer $id ID for searched weblog + * @return boolean exists or not + */ + public function existsID($id) + { + $r = DB::getResult('SELECT * FROM '.sql_table('blog').' WHERE bnumber='.intval($id)); + return ($r->rowCount() != 0); + } + + /** + * Blog::setFuturePost() + * flag there is a future post pending + * + * @param void + * @return void + */ + public function setFuturePost() + { + $query = "UPDATE %s SET bfuturepost='1' WHERE bnumber=%d;"; + $query = sprintf($query, sql_table('blog'), (integer) $this->blogid); + DB::execute($query); + return; + } + + /** + * Blog::clearFuturePost() + * clear there is a future post pending + * + * @param void + * @return void + */ + public function clearFuturePost() + { + $query = "UPDATE %s SET bfuturepost='0' WHERE bnumber=%d;"; + $query = sprintf($query, sql_table('blog'), (integer) $this->blogid); + DB::execute($query); + return; + } + + /** + * Blog::checkJustPosted() + * check if we should throw justPosted event + * + * @param void + * @return void + */ + public function checkJustPosted() + { + global $manager; + + if ( $this->settings['bfuturepost'] == 1 ) + { + $query = "SELECT * FROM %s WHERE iposted=0 AND iblog=%d AND itime < NOW();"; + $query = sprintf($query, sql_table('item'), (integer) $this->blogid); + + $result = DB::getResult($query); + if ( $result->rowCount() > 0 ) + { + // This $pinged is allow a plugin to tell other hook to the event that a ping is sent already + // Note that the plugins's calling order is subject to thri order in the plugin list + $pinged = FALSE; + $data = array('blogid' => $this->blogid, 'pinged' => &$pinged); + $manager->notify('JustPosted', $data); + + // clear all expired future posts + $query = "UPDATE %s SET iposted='1' WHERE iblog=%d AND itime < NOW();"; + $query = spriintf($query, sql_table('item'), (integer) $this->blogid); + DB::execute($query); + + // check to see any pending future post, clear the flag is none + $query = "SELECT * FROM %s WHERE iposted=0 AND iblog=%d;"; + $query = sprintf($query, sql_table('item'), (integer) $this->blogid); + + $result = DB::getResult($query); + if ( $result->rowCount() == 0 ) + { + $this->clearFuturePost(); + } + } + } + return; + } + + /** + * Blog::readLogFromList() + * Shows the given list of items for this blog + * + * @param array $itemarray array of item numbers to be displayed + * @param string $template string representing the template _NAME_ (!) + * @param string $highlight contains a query that should be highlighted + * @param boolean $comments 1=show comments 0=don't show comments + * @param boolean $dateheads 1=show dateheads 0=don't show dateheads + * @param boolean $showDrafts 0=do not show drafts 1=show drafts + * @param boolean $showFuture 0=do not show future posts 1=show future posts + * @return integer amount of items shown + */ + public function readLogFromList($itemarray, $template, $highlight = '', $comments = 1, $dateheads = 1,$showDrafts = 0, $showFuture = 0) + { + $query = $this->getSqlItemList($itemarray,$showDrafts,$showFuture); + return $this->showUsingQuery($template, $query, $highlight, $comments, $dateheads); + } + + /** + * Blog::getSqlItemList() + * Returns the SQL query used to fill out templates for a list of items + * No LIMIT clause is added. (caller should add this if multiple pages are requested) + * + * @param array $itemarray an array holding the item numbers of the items to be displayed + * @param integer $showDrafts 0=do not show drafts 1=show drafts + * @param integer $showFuture 0=do not show future posts 1=show future posts + * @return string either a full SQL query, or an empty string + */ + public function getSqlItemList($itemarray,$showDrafts = 0,$showFuture = 0) + { + if ( !is_array($itemarray) ) + { + return ''; + } + + $showDrafts = intval($showDrafts); + $showFuture = intval($showFuture); + $items = array(); + + foreach ( $itemarray as $value ) + { + if ( intval($value) ) + { + $items[] = intval($value); + } + } + if ( !count($items) ) + { + return ''; + } + + $i = count($items); + $query = ''; + foreach ( $items as $value ) + { + $query .= '(' + . 'SELECT' + . ' i.inumber as itemid,' + . ' i.ititle as title,' + . ' i.ibody as body,' + . ' m.mname as author,' + . ' m.mrealname as authorname,' + . ' i.itime,' + . ' i.imore as more,' + . ' m.mnumber as authorid,' + . ' m.memail as authormail,' + . ' m.murl as authorurl,' + . ' c.cname as category,' + . ' i.icat as catid,' + . ' i.iclosed as closed'; + + $query .= ' FROM ' + . sql_table('item') . ' as i, ' + . sql_table('member') . ' as m, ' + . sql_table('category') . ' as c' + . ' WHERE' + . ' i.iblog='.$this->blogid + . ' and i.iauthor=m.mnumber' + . ' and i.icat=c.catid'; + + // exclude drafts + if ( !$showDrafts ) + { + $query .= ' and i.idraft=0'; + } + if ( !$showFuture ) + { + // don't show future items + $query .= ' and i.itime<=' . DB::formatDateTime($this->getCorrectTime()); + } + + $query .= ' and i.inumber='.intval($value); + $query .= ')'; + $i--; + if ($i) $query .= ' UNION '; + } + + return $query; + } + + /** + * Blog::convertBreaks() + * Get the the setting for the line break handling + * [should be named as getConvertBreaks()] + * + * @deprecated + * @param void + * @return + */ + public function convertBreaks() + { + return $this->getSetting('bconvertbreaks'); + } + + /** + * Set the the setting for the line break handling + * + * @deprecated + * @param boolean $val new value for bconvertbreaks + * @return void + */ + public function setConvertBreaks($val) + { + $this->setSetting('bconvertbreaks', $val); + return; + } + } ++>>>>>>> skinnable-master diff --combined nucleus/libs/BODYACTIONS.php index 137af90,06b4f9d..8464021 --- a/nucleus/libs/BODYACTIONS.php +++ b/nucleus/libs/BODYACTIONS.php @@@ -15,7 -15,7 +15,11 @@@ * * @license http://nucleuscms.org/license.txt GNU General Public License * @copyright Copyright (C) 2002-2009 The Nucleus Group ++<<<<<<< HEAD + * @version $Id: BODYACTIONS.php 1757 2012-04-15 09:02:32Z sakamocchi $ ++======= + * @version $Id: BODYACTIONS.php 1886 2012-06-17 08:27:27Z sakamocchi $ ++>>>>>>> skinnable-master */ class BodyActions extends BaseActions @@@ -39,7 -39,7 +43,11 @@@ */ public function __construct() { ++<<<<<<< HEAD + parent::__construct(); ++======= + parent::__construct(); ++>>>>>>> skinnable-master return; } @@@ -107,9 -107,10 +115,16 @@@ array_shift($params); // add item reference (array_unshift didn't work) ++<<<<<<< HEAD + $params = array_merge(array(&$this->currentItem), $params); + + call_user_func_array(array(&$plugin, 'doItemVar'), $params); ++======= + $target = array(&$this->currentItem); + $params = array_merge($target, $params); + + call_user_func_array(array($plugin, 'doItemVar'), $params); ++>>>>>>> skinnable-master return; } @@@ -126,7 -127,7 +141,11 @@@ // image/popup calls have arguments separated by | $args = func_get_args(); $args = preg_split('#\|#', implode($args, ', ')); ++<<<<<<< HEAD + echo call_user_func_array(array(&$this, 'createImageCode'), $args); ++======= + echo call_user_func_array(array($this, 'createImageCode'), $args); ++>>>>>>> skinnable-master } /** @@@ -174,7 -175,7 +193,11 @@@ // image/popup calls have arguments separated by | $args = func_get_args(); $args = preg_split('#\|#', implode($args, ', ')); ++<<<<<<< HEAD + echo call_user_func_array(array(&$this, 'createMediaCode'), $args); ++======= + echo call_user_func_array(array($this, 'createMediaCode'), $args); ++>>>>>>> skinnable-master } /** @@@ -215,7 -216,7 +238,11 @@@ // image/popup calls have arguments separated by | $args = func_get_args(); $args = preg_split('#\|#', implode($args, ', ')); ++<<<<<<< HEAD + echo call_user_func_array(array(&$this, 'createPopupCode'), $args); ++======= + echo call_user_func_array(array($this, 'createPopupCode'), $args); ++>>>>>>> skinnable-master } /** @@@ -280,7 -281,7 +307,11 @@@ $condition = ($blog && ($blog->getSetting($name) == $value)); break; case 'itemblogsetting': ++<<<<<<< HEAD + $b =& $manager->getBlog(getBlogIDFromItemID($this->currentItem['itemid'])); ++======= + $b =& $manager->getBlog($this->currentItem['blogid']); ++>>>>>>> skinnable-master $condition = ($b && ($b->getSetting($name) == $value)); break; case 'loggedin': @@@ -354,7 -355,7 +385,11 @@@ { global $member, $manager; ++<<<<<<< HEAD + $b =& $manager->getBlog(getBlogIDFromItemID($this->currentItem['itemid'])); ++======= + $b =& $manager->getBlog($this->currentItem['blogid']); ++>>>>>>> skinnable-master // when no parameter is defined, just check if author is current visitor if ( ($key != 'isadmin' && $key != 'name') || ($key == 'name' && $value == '') ) @@@ -400,7 -401,7 +435,11 @@@ { global $catid, $manager; ++<<<<<<< HEAD + $b =& $manager->getBlog(getBlogIDFromItemID($this->currentItem['itemid'])); ++======= + $b =& $manager->getBlog($this->currentItem['blogid']); ++>>>>>>> skinnable-master // when no parameter is defined, just check if a category is selected if ( ($key != 'catname' && $key != 'catid') || ($value == '') ) @@@ -558,6 -559,6 +597,10 @@@ $params = func_get_args(); array_shift($params); ++<<<<<<< HEAD + return call_user_func_array(array(&$plugin, 'doIf'), $params); ++======= + return call_user_func_array(array($plugin, 'doIf'), $params); ++>>>>>>> skinnable-master } } diff --combined nucleus/libs/BaseActions.php index 9473d52,410804e..6ae996b --- a/nucleus/libs/BaseActions.php +++ b/nucleus/libs/BaseActions.php @@@ -17,7 -17,7 +17,11 @@@ * * @license http://nucleuscms.org/license.txt GNU General Public License * @copyright Copyright (C) 2002-2009 The Nucleus Group ++<<<<<<< HEAD + * @version $Id: BaseActions.php 1848 2012-05-16 12:17:00Z sakamocchi $ ++======= + * @version $Id: BaseActions.php 1882 2012-06-17 07:52:43Z sakamocchi $ ++>>>>>>> skinnable-master */ class BaseActions @@@ -139,14 -139,14 +143,22 @@@ /** * BaseActions::parse_locale() ++<<<<<<< HEAD + * Parse locale to language-script-region according to RFC 4646 ++======= + * Parse locale to language-region according to RFC 4646 ++>>>>>>> skinnable-master * * @param void * @return void */ public function parse_locale() { ++<<<<<<< HEAD + echo preg_replace('#_#', '-', i18n::get_current_locale()); ++======= + echo preg_replace('#(.+)_(.+)_(.+)#', '$1-$3', i18n::get_current_locale()); ++>>>>>>> skinnable-master return; } @@@ -434,7 -434,7 +446,11 @@@ { $this->addIfExecute(); $args = func_get_args(); ++<<<<<<< HEAD + $condition = call_user_func_array(array(&$this,'checkCondition'), $args); ++======= + $condition = call_user_func_array(array($this,'checkCondition'), $args); ++>>>>>>> skinnable-master $this->addIfCondition($condition); return; } @@@ -505,7 -505,7 +521,11 @@@ { ob_end_clean(); $args = func_get_args(); ++<<<<<<< HEAD + $condition = call_user_func_array(array(&$this,'checkCondition'), $args); ++======= + $condition = call_user_func_array(array($this,'checkCondition'), $args); ++>>>>>>> skinnable-master $this->addIfCondition($condition); } return; @@@ -523,7 -523,7 +543,11 @@@ $this->addIfExecute(); $args = func_get_args(); ++<<<<<<< HEAD + $condition = call_user_func_array(array(&$this,'checkCondition'), $args); ++======= + $condition = call_user_func_array(array($this,'checkCondition'), $args); ++>>>>>>> skinnable-master $this->addIfCondition(!$condition); return; } @@@ -559,7 -559,7 +583,11 @@@ { ob_end_clean(); $args = func_get_args(); ++<<<<<<< HEAD + $condition = call_user_func_array(array(&$this,'checkCondition'), $args); ++======= + $condition = call_user_func_array(array($this,'checkCondition'), $args); ++>>>>>>> skinnable-master $this->addIfCondition(!$condition); } return; diff --combined nucleus/libs/COMMENT.php index bb38e11,22f8926..3cb7daa --- a/nucleus/libs/COMMENT.php +++ b/nucleus/libs/COMMENT.php @@@ -1,229 -1,229 +1,461 @@@ ++<<<<<<< HEAD + tags + $body = addBreaks($body); + + // create hyperlinks for http:// addresses + // there's a testcase for this in /build/testcases/urllinking.txt + $replace_from = array( + '/([^:\/\/\w]|^)((https:\/\/)([\w\.-]+)([\/\w+\.~%&?@=_:;#,-]+))/i', + '/([^:\/\/\w]|^)((http:\/\/|www\.)([\w\.-]+)([\/\w+\.~%&?@=_:;#,-]+))/i', + '/([^:\/\/\w]|^)((ftp:\/\/|ftp\.)([\w\.-]+)([\/\w+\.~%&?@=_:;#,-]+))/i', + '/([^:\/\/\w]|^)(mailto:(([a-zA-Z\@\%\.\-\+_])+))/i' + ); + + return preg_replace_callback($replace_from, array(__CLASS__, 'prepareBody_cb'), $body); + } + + /** + * Comment::createLinkCode() + * Creates a link code for unlinked URLs with different protocols + * + * @static + * @param string $pre Prefix of comment + * @param string $url URL + * @param string $protocol http, mailto and so on + * @return string string including anchor element and child text + */ + static private function createLinkCode($pre, $url, $protocol = 'http') + { + $post = ''; + + // it's possible that $url ends contains entities we don't want, + // since htmlspecialchars is applied _before_ URL linking + // move the part of URL, starting from the disallowed entity to the 'post' link part + $aBadEntities = array('"', '>', '<'); + foreach ( $aBadEntities as $entity ) + { + $pos = i18n::strpos($url, $entity); + + if ( $pos ) + { + $post = i18n::substr($url, $pos) . $post; + $url = i18n::substr($url, 0, $pos); + } + } + + // remove entities at end (&&&&) + if ( preg_match('/(&\w+;)+$/i', $url, $matches) ) + { + $post = $matches[0] . $post; // found entities (1 or more) + $url = i18n::substr($url, 0, i18n::strlen($url) - i18n::strlen($post) ); + } + + // move ending comma from url to 'post' part + if ( i18n::substr($url, i18n::strlen($url) - 1) == ',' ) + { + $url = i18n::substr($url, 0, i18n::strlen($url) - 1); + $post = ',' . $post; + } + + if ( !preg_match('#^' . $protocol . '://#', $url) ) + { + $linkedUrl = $protocol . ( ($protocol == 'mailto') ? ':' : '://') . $url; + } + else + { + $linkedUrl = $url; + } + + if ( $protocol != 'mailto' ) + { + $displayedUrl = $linkedUrl; + } + else + { + $displayedUrl = $url; + } + + return $pre . '' . Entity::hsc(Entity::shorten($displayedUrl,30,'...')) . '' . $post; + } + + /** + * Comment::prepareBody_cb() + * This method is a callback for creating link codes + * + * @param array $match elements for achor + * @return string including anchor element and child text + * + */ + static public function prepareBody_cb($match) + { + if ( !preg_match('/^[a-z]+/i', $match[2], $protocol) ) + { + return $match[0]; + } + + switch( strtolower($protocol[0]) ) + { + case 'https': + return self::createLinkCode($match[1], $match[2], 'https'); + break; + + case 'ftp': + return self::createLinkCode($match[1], $match[2], 'ftp'); + break; + + case 'mailto': + return self::createLinkCode($match[1], $match[3], 'mailto'); + break; + + default: + return self::createLinkCode($match[1], $match[2], 'http'); + break; + } + return; + } +} ++======= + tags + $body = addBreaks($body); + + // create hyperlinks for http:// addresses + // there's a testcase for this in /build/testcases/urllinking.txt + $replace_from = array( + '/([^:\/\/\w]|^)((https:\/\/)([\w\.-]+)([\/\w+\.~%&?@=_:;#,-]+))/i', + '/([^:\/\/\w]|^)((http:\/\/|www\.)([\w\.-]+)([\/\w+\.~%&?@=_:;#,-]+))/i', + '/([^:\/\/\w]|^)((ftp:\/\/|ftp\.)([\w\.-]+)([\/\w+\.~%&?@=_:;#,-]+))/i', + '/([^:\/\/\w]|^)(mailto:(([a-zA-Z\@\%\.\-\+_])+))/i' + ); + + return preg_replace_callback($replace_from, array(__CLASS__, 'prepareBody_cb'), $body); + } + + /** + * Comment::createLinkCode() + * Creates a link code for unlinked URLs with different protocols + * + * @static + * @param string $pre Prefix of comment + * @param string $url URL + * @param string $protocol http, mailto and so on + * @return string string including anchor element and child text + */ + static private function createLinkCode($pre, $url, $protocol = 'http') + { + $post = ''; + + // it's possible that $url ends contains entities we don't want, + // since htmlspecialchars is applied _before_ URL linking + // move the part of URL, starting from the disallowed entity to the 'post' link part + $aBadEntities = array('"', '>', '<'); + foreach ( $aBadEntities as $entity ) + { + $pos = i18n::strpos($url, $entity); + + if ( $pos ) + { + $post = i18n::substr($url, $pos) . $post; + $url = i18n::substr($url, 0, $pos); + } + } + + // remove entities at end (&&&&) + if ( preg_match('/(&\w+;)+$/i', $url, $matches) ) + { + $post = $matches[0] . $post; // found entities (1 or more) + $url = i18n::substr($url, 0, i18n::strlen($url) - i18n::strlen($post) ); + } + + // move ending comma from url to 'post' part + if ( i18n::substr($url, i18n::strlen($url) - 1) == ',' ) + { + $url = i18n::substr($url, 0, i18n::strlen($url) - 1); + $post = ',' . $post; + } + + if ( !preg_match('#^' . $protocol . '://#', $url) ) + { + $linkedUrl = $protocol . ( ($protocol == 'mailto') ? ':' : '://') . $url; + } + else + { + $linkedUrl = $url; + } + + if ( $protocol != 'mailto' ) + { + $displayedUrl = $linkedUrl; + } + else + { + $displayedUrl = $url; + } + + return $pre . '' . Entity::hsc(Entity::shorten($displayedUrl,30,'...')) . '' . $post; + } + + /** + * Comment::prepareBody_cb() + * This method is a callback for creating link codes + * + * @param array $match elements for achor + * @return string including anchor element and child text + * + */ + static public function prepareBody_cb($match) + { + if ( !preg_match('/^[a-z]+/i', $match[2], $protocol) ) + { + return $match[0]; + } + + switch( strtolower($protocol[0]) ) + { + case 'https': + return self::createLinkCode($match[1], $match[2], 'https'); + break; + + case 'ftp': + return self::createLinkCode($match[1], $match[2], 'ftp'); + break; + + case 'mailto': + return self::createLinkCode($match[1], $match[3], 'mailto'); + break; + + default: + return self::createLinkCode($match[1], $match[2], 'http'); + break; + } + return; + } + } ++>>>>>>> skinnable-master diff --combined nucleus/libs/COMMENTACTIONS.php index b320145,96bdb10..8ef2afb --- a/nucleus/libs/COMMENTACTIONS.php +++ b/nucleus/libs/COMMENTACTIONS.php @@@ -232,8 -232,8 +232,13 @@@ class CommentActions extends BaseAction public function parse_blogurl() { global $manager; ++<<<<<<< HEAD + $blogid = getBlogIDFromItemID($this->commentsObj->itemid); + $blog =& $manager->getBlog($blogid); ++======= + $item =& $manager->getItem($this->commentsObj->itemid, 1, 1); + $blog =& $manager->getBlog($item['blogid']); ++>>>>>>> skinnable-master echo $blog->getURL(); return; } @@@ -537,10 -537,12 +542,19 @@@ array_shift($params); // pass info on current item and current comment as well ++<<<<<<< HEAD + $params = array_merge(array(&$this->currentComment), $params); + $params = array_merge(array(&$this->commentsObj->itemActions->currentItem), $params); + + call_user_func_array(array(&$plugin,'doTemplateCommentsVar'), $params); ++======= + $target = array(&$this->currentComment); + $params = array_merge($target, $params); + $target = array(&$this->commentsObj->itemActions->currentItem); + $params = array_merge($target, $params); + + call_user_func_array(array($plugin,'doTemplateCommentsVar'), $params); ++>>>>>>> skinnable-master return; } @@@ -641,7 -643,7 +655,11 @@@ */ public function parse_userlinkraw() { ++<<<<<<< HEAD + echo $this->currentComment['userlinkraw']; ++======= + echo (array_key_exists('userlinkraw', $this->currentComment) && !empty($this->currentComment['userlinkraw'])) ? $this->currentComment['userlinkraw'] : ''; ++>>>>>>> skinnable-master return; } @@@ -705,8 -707,9 +723,14 @@@ $condition = ($blog && ($blog->getSetting($name) == $value)); break; case 'itemblogsetting': ++<<<<<<< HEAD + $b =& $manager->getBlog(getBlogIDFromItemID($this->currentComment['itemid'])); + $condition = ($b && ($b->getSetting($name) == $value)); ++======= + $item =& $manager->getItem($this->currentComment['itemid'], 1, 1); + $blog =& $manager->getBlog($item['blogid']); + $condition = ($blog && ($blog->getSetting($name) == $value)); ++>>>>>>> skinnable-master break; case 'loggedin': $condition = $member->isLoggedIn(); @@@ -781,13 -784,13 +805,23 @@@ return FALSE; } ++<<<<<<< HEAD + $mem =& $manager->getMember($this->currentComment['memberid']); + $b =& $manager->getBlog(getBlogIDFromItemID($this->currentComment['itemid'])); + $citem =& $manager->getItem($this->currentComment['itemid'], 1, 1); + + // when no parameter is defined, just check if item author is current visitor + if (($key != 'isadmin' && $key != 'name' && $key != 'isauthor' && $key != 'isonteam')) { + return (intval($member->getID()) > 0 && intval($member->getID()) == intval($citem['authorid'])); ++======= + $member =& $manager->getMember($this->currentComment['memberid']); + $item =& $manager->getItem($this->currentComment['itemid'], 1, 1); + + // when no parameter is defined, just check if item author is current visitor + if ( ($key != 'isadmin' && $key != 'name' && $key != 'isauthor' && $key != 'isonteam') ) + { + return (intval($memberber->getID()) > 0 && intval($memberber->getID()) == (integer) $item['authorid']); ++>>>>>>> skinnable-master } // check comment author name @@@ -798,7 -801,7 +832,11 @@@ { return FALSE; } ++<<<<<<< HEAD + if ( $value == strtolower($mem->getDisplayName()) ) ++======= + if ( $value == strtolower($member->getDisplayName()) ) ++>>>>>>> skinnable-master { return TRUE; } @@@ -807,24 -810,23 +845,40 @@@ // check if comment author is admin if ( $key == 'isadmin' ) { ++<<<<<<< HEAD + $blogid = intval($b->getID()); + if ( $mem->isAdmin() ) + { + return TRUE; + } + return $mem->isBlogAdmin($blogid); ++======= + if ( $member->isAdmin() ) + { + return TRUE; + } + return $member->isBlogAdmin($item['blogid']); ++>>>>>>> skinnable-master } // check if comment author is item author if ( $key == 'isauthor' ) { ++<<<<<<< HEAD + return (intval($citem['authorid']) == intval($this->currentComment['memberid'])); ++======= + return ((integer) $item['authorid'] == (integer) $this->currentComment['memberid']); ++>>>>>>> skinnable-master } // check if comment author is on team if ( $key == 'isonteam' ) { ++<<<<<<< HEAD + return $mem->teamRights(intval($b->getID())); ++======= + return $member->teamRights((integer) $item['blogid']); ++>>>>>>> skinnable-master } return FALSE; } @@@ -840,31 -842,30 +894,58 @@@ private function ifItemCategory($key = '', $value = '') { global $catid, $manager; ++<<<<<<< HEAD + + $b =& $manager->getBlog(getBlogIDFromItemID($this->currentComment['itemid'])); + $citem =& $manager->getItem($this->currentComment['itemid'],1,1); + $icatid = $citem['catid']; + + // when no parameter is defined, just check if a category is selected + if ( ($key != 'catname' && $key != 'catid') || ($value == '') ) + { + return $b->isValidCategory($icatid); + } + + // check category name + if ( $key == 'catname' ) + { + $value = $b->getCategoryIdFromName($value); + if ( $value == $icatid ) + { + return $b->isValidCategory($icatid); + } + } + + // check category id + if ( ($key == 'catid') && ($value == $icatid) ) + { + return $b->isValidCategory($icatid); ++======= + + $item =& $manager->getItem($this->currentComment['itemid'],1,1); + $blog =& $manager->getBlog($item['blogid']); + + // when no parameter is defined, just check if a category is selected + if ( ($key != 'catname' && $key != 'catid') || ($value == '') ) + { + return $blog->isValidCategory($item['catid']); + } + + // check category name + if ( $key == 'catname' ) + { + $value = $blog->getCategoryIdFromName($value); + if ( $value == $item['catid'] ) + { + return $blog->isValidCategory($item['catid']); + } + } + + // check category id + if ( ($key == 'catid') && ($value == $item['catid']) ) + { + return $blog->isValidCategory($item['catid']); ++>>>>>>> skinnable-master } return FALSE; } @@@ -878,12 -879,13 +959,22 @@@ */ private function ifOnTeam($blogName = '') { ++<<<<<<< HEAD + global $blog, $member, $manager; + + $b =& $manager->getBlog(getBlogIDFromItemID($this->currentComment['itemid'])); + + // when no blog found + if ( ($blogName == '') && (!is_object($b)) ) ++======= + global $member, $manager; + + $item =& $manager->getItem($this->currentComment['itemid'], 1, 1); + $blog =& $manager->getBlog($item['blogid']); + + // when no blog found + if ( ($blogName == '') && !is_object($blog) ) ++>>>>>>> skinnable-master { return 0; } @@@ -897,7 -899,7 +988,11 @@@ // use current blog if ( ($blogName == '') || !$manager->existsBlogID($blogid) ) { ++<<<<<<< HEAD + $blogid = $b->getID(); ++======= + $blogid = $blog->getID(); ++>>>>>>> skinnable-master } return $member->teamRights($blogid); @@@ -912,12 -914,13 +1007,22 @@@ */ private function ifAdmin($blogName = '') { ++<<<<<<< HEAD + global $blog, $member, $manager; + + $b =& $manager->getBlog(getBlogIDFromItemID($this->currentComment['itemid'])); + + // when no blog found + if ( ($blogName == '') && (!is_object($b)) ) ++======= + global $member, $manager; + + $item =& $manager->getItem($this->currentComment['itemid'], 1, 1); + $blog =& $manager->getBlog($item['blogid']); + + // when no blog found + if ( ($blogName == '') && !is_object($blog) ) ++>>>>>>> skinnable-master { return 0; } @@@ -931,7 -934,7 +1036,11 @@@ // use current blog if ( ($blogName == '') || !$manager->existsBlogID($blogid) ) { ++<<<<<<< HEAD + $blogid = $b->getID(); ++======= + $blogid = $blog->getID(); ++>>>>>>> skinnable-master } return $member->isBlogAdmin($blogid); @@@ -1004,6 -1007,6 +1113,10 @@@ $params = func_get_args(); array_shift($params); ++<<<<<<< HEAD + return call_user_func_array(array(&$plugin, 'doIf'), $params); ++======= + return call_user_func_array(array($plugin, 'doIf'), $params); ++>>>>>>> skinnable-master } } diff --combined nucleus/libs/COMMENTS.php index 6783c06,4376f16..5eaf79d --- a/nucleus/libs/COMMENTS.php +++ b/nucleus/libs/COMMENTS.php @@@ -1,442 -1,447 +1,892 @@@ ++<<<<<<< HEAD +itemid = (integer) $itemid; + return; + } + + /** + * Comments::setItemActions() + * Used when parsing comments + * + * @param object $itemActions itemActions object, that will take care of the parsing + * @return void + */ + public function setItemActions(&$itemActions) + { + $this->itemActions =& $itemActions; + return; + } + + /** + * Comments::showComments() + * Shows maximum $max comments to the given item using the given template + * returns the amount of shown comments (if maxToShow = -1, then there is no limit) + * + * @param array template template to use + * @param integer maxToShow max. comments to show + * @param integer showNone indicates if the 'no comments' thingie should be outputted + * when there are no comments (useful for closed items) + * @param string highlight Highlight to use (if any) + * @return integer number of comments + */ + public function showComments($template, $maxToShow = -1, $showNone = 1, $highlight = '') + { + global $CONF, $manager; + + if ( $maxToShow == 0 ) + { + $this->commentcount = $this->amountComments(); + } + else + { + $query = 'SELECT citem as itemid, cnumber as commentid, cbody as body, cuser as user, cmail as userid, ' + . 'cemail as email, cmember as memberid, ctime, chost as host, cip as ip, cblog as blogid ' + . 'FROM %s as c WHERE citem=%d ORDER BY ctime'; + + $query = sprintf($query, sql_table('comment'), (integer) $this->itemid); + $comments = DB::getResult($query); + $this->commentcount = $comments->rowCount(); + } + + // create parser object & action handler + $handler = new CommentActions($this); + $handler->setTemplate($template); + + $parser = new Parser($handler); + + // if no result was found + if ( $this->commentcount == 0 ) + { + // note: when no reactions, COMMENTS_HEADER and COMMENTS_FOOTER are _NOT_ used + if ( $showNone ) + { + $parser->parse($template['COMMENTS_NONE']); + } + return 0; + } + + // if too many comments to show + if ( ($maxToShow != -1) && ($this->commentcount > $maxToShow) ) + { + $parser->parse($template['COMMENTS_TOOMUCH']); + return 0; + } + + $parser->parse($template['COMMENTS_HEADER']); + + foreach ( $comments as $comment ) + { + $comment['timestamp'] = strtotime($comment['ctime']); + $handler->setCurrentComment($comment); + $handler->setHighlight($highlight); + + $manager->notify('PreComment', array('comment' => &$comment)); + $parser->parse($template['COMMENTS_BODY']); + $manager->notify('PostComment', array('comment' => &$comment)); + } + + $parser->parse($template['COMMENTS_FOOTER']); + + $comments->closeCursor(); + + return $this->commentcount; + } + + /** + * Comments::amountComments() + * Returns the amount of comments for this itemid + * + * @param void + * @return integer number of comments + */ + public function amountComments() + { + $query = 'SELECT COUNT(*) FROM %s WHERE citem=%d;'; + $query = sprintf($query, sql_table('comment'), (integer) $this->itemid); + $res = DB::getValue($query); + + return $res; + } + + /** + * Comments::addComment() + * Adds a new comment to the database + * + * @param string $timestamp + * @param array $comment + * @return mixed + */ + public function addComment($timestamp, $comment) + { + global $CONF, $member, $manager; + + $blogid = getBlogIDFromItemID($this->itemid); + + $settings =& $manager->getBlog($blogid); + $settings->readSettings(); + + // begin if: comments disabled + if ( !$settings->commentsEnabled() ) + { + return _ERROR_COMMENTS_DISABLED; + } + + // begin if: public cannot comment + if ( !$settings->isPublic() && !$member->isLoggedIn() ) + { + return _ERROR_COMMENTS_NONPUBLIC; + } + + // begin if: comment uses a protected member name + if ( $CONF['ProtectMemNames'] && !$member->isLoggedIn() && Member::isNameProtected($comment['user']) ) + { + return _ERROR_COMMENTS_MEMBERNICK; + } + + // begin if: email required, but missing (doesn't apply to members) + if ( $settings->emailRequired() && i18n::strlen($comment['email']) == 0 && !$member->isLoggedIn() ) + { + return _ERROR_EMAIL_REQUIRED; + } + + // begin if: commenter's name is too long + if ( i18n::strlen($comment['user']) > 40 ) + { + return _ERROR_USER_TOO_LONG; + } + + // begin if: commenter's email is too long + if ( i18n::strlen($comment['email']) > 100 ) + { + return _ERROR_EMAIL_TOO_LONG; + } + + // begin if: commenter's url is too long + if ( i18n::strlen($comment['userid']) > 100 ) + { + return _ERROR_URL_TOO_LONG; + } + + $comment['timestamp'] = $timestamp; + $comment['host'] = gethostbyaddr(serverVar('REMOTE_ADDR') ); + $comment['ip'] = serverVar('REMOTE_ADDR'); + + // begin if: member is logged in, use that data + if ( $member->isLoggedIn() ) + { + $comment['memberid'] = $member->getID(); + $comment['user'] = ''; + $comment['userid'] = ''; + $comment['email'] = ''; + } + else + { + $comment['memberid'] = 0; + } + + // spam check + $continue = FALSE; + $plugins = array(); + + if ( isset($manager->subscriptions['ValidateForm']) ) + { + $plugins = array_merge($plugins, $manager->subscriptions['ValidateForm']); + } + + if ( isset($manager->subscriptions['PreAddComment']) ) + { + $plugins = array_merge($plugins, $manager->subscriptions['PreAddComment']); + } + + if ( isset($manager->subscriptions['PostAddComment']) ) + { + $plugins = array_merge($plugins, $manager->subscriptions['PostAddComment']); + } + + $plugins = array_unique($plugins); + + while ( list(, $plugin) = each($plugins) ) + { + $p = $manager->getPlugin($plugin); + $continue = $continue || $p->supportsFeature('handleSpam'); + } + + $spamcheck = array( + 'type' => 'comment', + 'body' => $comment['body'], + 'id' => $comment['itemid'], + 'live' => TRUE, + 'return' => $continue + ); + + // begin if: member logged in + if ( $member->isLoggedIn() ) + { + $spamcheck['author'] = $member->displayname; + $spamcheck['email'] = $member->email; + } + // else: public + else + { + $spamcheck['author'] = $comment['user']; + $spamcheck['email'] = $comment['email']; + $spamcheck['url'] = $comment['userid']; + } + + $manager->notify('SpamCheck', array('spamcheck' => &$spamcheck) ); + + if ( !$continue && isset($spamcheck['result']) && $spamcheck['result'] == TRUE ) + { + return _ERROR_COMMENTS_SPAM; + } + + // isValidComment returns either "1" or an error message + $isvalid = $this->isValidComment($comment, $spamcheck); + if ( $isvalid != 1 ) + { + return $isvalid; + } + + // begin if: send email to notification address + if ( $settings->getNotifyAddress() && $settings->notifyOnComment() ) + { + + $message = _NOTIFY_NC_MSG . ' ' . $this->itemid . "\n"; + $temp = parse_url($CONF['Self']); + + if ( $temp['scheme'] ) + { + $message .= Link::create_item_link($this->itemid) . "\n\n"; + } + else + { + $tempurl = $settings->getURL(); + + if ( i18n::substr($tempurl, -1) == '/' || i18n::substr($tempurl, -4) == '.php' ) + { + $message .= $tempurl . '?itemid=' . $this->itemid . "\n\n"; + } + else + { + $message .= $tempurl . '/?itemid=' . $this->itemid . "\n\n"; + } + } + + if ( $comment['memberid'] == 0 ) + { + $message .= _NOTIFY_USER . ' ' . $comment['user'] . "\n"; + $message .= _NOTIFY_USERID . ' ' . $comment['userid'] . "\n"; + } + else + { + $message .= _NOTIFY_MEMBER .' ' . $member->getDisplayName() . ' (ID=' . $member->getID() . ")\n"; + } + + $message .= _NOTIFY_HOST . ' ' . $comment['host'] . "\n"; + $message .= _NOTIFY_COMMENT . "\n " . $comment['body'] . "\n"; + $message .= NOTIFICATION::get_mail_footer(); + + $item =& $manager->getItem($this->itemid, 0, 0); + $subject = _NOTIFY_NC_TITLE . ' ' . strip_tags($item['title']) . ' (' . $this->itemid . ')'; + + $from = $member->getNotifyFromMailAddress($comment['email']); + + NOTIFICATION::mail($settings->getNotifyAddress(), $subject, $message, $from, i18n::get_current_charset()); + } + + $comment = Comment::prepare($comment); + + $manager->notify('PreAddComment', array('comment' => &$comment, 'spamcheck' => &$spamcheck) ); + + $name = DB::quoteValue($comment['user']); + $url = DB::quoteValue($comment['userid']); + $email = DB::quoteValue($comment['email']); + $body = DB::quoteValue($comment['body']); + $host = DB::quoteValue($comment['host']); + $ip = DB::quoteValue($comment['ip']); + $memberid = intval($comment['memberid']); + $timestamp = DB::formatDateTime($comment['timestamp']); + $itemid = $this->itemid; + + $qSql = 'SELECT COUNT(*) AS result ' + . 'FROM ' . sql_table('comment') + . ' WHERE ' + . 'cmail = ' . $url + . ' AND cmember = ' . $memberid + . ' AND cbody = ' . $body + . ' AND citem = ' . $itemid + . ' AND cblog = ' . $blogid; + $result = (integer) DB::getValue($qSql); + + if ( $result > 0 ) + { + return _ERROR_BADACTION; + } + + $query = sprintf('INSERT INTO %s (cuser, cmail, cemail, cmember, cbody, citem, ctime, chost, cip, cblog) ' + . 'VALUES (%s, %s, %s, %d, %s, %d, %s, %s, %s, %d)' + , sql_table('comment'), $name, $url, $email, $memberid, $body, $itemid, $timestamp, $host, $ip, $blogid); + + DB::execute($query); + + // post add comment + $commentid = DB::getInsertId(); + $manager->notify('PostAddComment', array('comment' => &$comment, 'commentid' => &$commentid, 'spamcheck' => &$spamcheck) ); + + // succeeded ! + return TRUE; + } + + /** + * Comments::isValidComment() + * Checks if a comment is valid and call plugins + * that can check if the comment is a spam comment + * + * @param array $comment array with comment elements + * @param array $spamcheck array with spamcheck elements + * @return boolean valid or not + */ + private function isValidComment(&$comment, &$spamcheck) + { + global $member, $manager; + + // check if there exists a item for this date + $item =& $manager->getItem($this->itemid, 0, 0); + + if ( !$item ) + { + return _ERROR_NOSUCHITEM; + } + + if ( $item['closed'] ) + { + return _ERROR_ITEMCLOSED; + } + + // don't allow words that are too long + if ( preg_match('/[a-zA-Z0-9|\.,;:!\?=\/\\\\]{90,90}/', $comment['body']) != 0 ) + { + return _ERROR_COMMENT_LONGWORD; + } + + // check lengths of comment + if ( i18n::strlen($comment['body']) < 3 ) + { + return _ERROR_COMMENT_NOCOMMENT; + } + + if ( i18n::strlen($comment['body']) > 5000 ) + { + return _ERROR_COMMENT_TOOLONG; + } + + // only check username if no member logged in + if ( !$member->isLoggedIn() && (i18n::strlen($comment['user']) < 2) ) + { + return _ERROR_COMMENT_NOUSERNAME; + } + + if ( (i18n::strlen($comment['email']) != 0) && !NOTIFICATION::address_validation(trim($comment['email'])) ) + { + return _ERROR_BADMAILADDRESS; + } + + // let plugins do verification (any plugin which thinks the comment is invalid + // can change 'error' to something other than '1') + $result = 1; + $manager->notify('ValidateForm', array('type' => 'comment', 'comment' => &$comment, 'error' => &$result, 'spamcheck' => &$spamcheck) ); + + return $result; + } +} ++======= + itemid = (integer) $itemid; + return; + } + + /** + * Comments::setItemActions() + * Used when parsing comments + * + * @param object $itemActions itemActions object, that will take care of the parsing + * @return void + */ + public function setItemActions(&$itemActions) + { + $this->itemActions =& $itemActions; + return; + } + + /** + * Comments::showComments() + * Shows maximum $max comments to the given item using the given template + * returns the amount of shown comments (if maxToShow = -1, then there is no limit) + * + * @param array template template to use + * @param integer maxToShow max. comments to show + * @param integer showNone indicates if the 'no comments' thingie should be outputted + * when there are no comments (useful for closed items) + * @param string highlight Highlight to use (if any) + * @return integer number of comments + */ + public function showComments($template, $maxToShow = -1, $showNone = 1, $highlight = '') + { + global $CONF, $manager; + + if ( $maxToShow == 0 ) + { + $this->commentcount = $this->amountComments(); + } + else + { + $query = 'SELECT citem as itemid, cnumber as commentid, cbody as body, cuser as user, cmail as userid, ' + . 'cemail as email, cmember as memberid, ctime, chost as host, cip as ip, cblog as blogid ' + . 'FROM %s as c WHERE citem=%d ORDER BY ctime'; + + $query = sprintf($query, sql_table('comment'), (integer) $this->itemid); + $comments = DB::getResult($query); + $this->commentcount = $comments->rowCount(); + } + + // create parser object & action handler + $handler = new CommentActions($this); + $handler->setTemplate($template); + + $parser = new Parser($handler); + + // if no result was found + if ( $this->commentcount == 0 ) + { + // note: when no reactions, COMMENTS_HEADER and COMMENTS_FOOTER are _NOT_ used + if ( $showNone ) + { + $parser->parse($template['COMMENTS_NONE']); + } + return 0; + } + + // if too many comments to show + if ( ($maxToShow != -1) && ($this->commentcount > $maxToShow) ) + { + $parser->parse($template['COMMENTS_TOOMUCH']); + return 0; + } + + $parser->parse($template['COMMENTS_HEADER']); + + foreach ( $comments as $comment ) + { + $comment['timestamp'] = strtotime($comment['ctime']); + $handler->setCurrentComment($comment); + $handler->setHighlight($highlight); + + $data = array('comment' => &$comment); + $manager->notify('PreComment', $data); + $parser->parse($template['COMMENTS_BODY']); + $manager->notify('PostComment', $data); + } + + $parser->parse($template['COMMENTS_FOOTER']); + + $comments->closeCursor(); + + return $this->commentcount; + } + + /** + * Comments::amountComments() + * Returns the amount of comments for this itemid + * + * @param void + * @return integer number of comments + */ + public function amountComments() + { + $query = 'SELECT COUNT(*) FROM %s WHERE citem=%d;'; + $query = sprintf($query, sql_table('comment'), (integer) $this->itemid); + $res = DB::getValue($query); + + return $res; + } + + /** + * Comments::addComment() + * Adds a new comment to the database + * + * @param string $timestamp + * @param array $comment + * @return mixed + */ + public function addComment($timestamp, $comment) + { + global $CONF, $member, $manager; + + $blogid = getBlogIDFromItemID($this->itemid); + + $settings =& $manager->getBlog($blogid); + $settings->readSettings(); + + // begin if: comments disabled + if ( !$settings->commentsEnabled() ) + { + return _ERROR_COMMENTS_DISABLED; + } + + // begin if: public cannot comment + if ( !$settings->isPublic() && !$member->isLoggedIn() ) + { + return _ERROR_COMMENTS_NONPUBLIC; + } + + // begin if: comment uses a protected member name + if ( $CONF['ProtectMemNames'] && !$member->isLoggedIn() && Member::isNameProtected($comment['user']) ) + { + return _ERROR_COMMENTS_MEMBERNICK; + } + + // begin if: email required, but missing (doesn't apply to members) + if ( $settings->emailRequired() && i18n::strlen($comment['email']) == 0 && !$member->isLoggedIn() ) + { + return _ERROR_EMAIL_REQUIRED; + } + + // begin if: commenter's name is too long + if ( i18n::strlen($comment['user']) > 40 ) + { + return _ERROR_USER_TOO_LONG; + } + + // begin if: commenter's email is too long + if ( i18n::strlen($comment['email']) > 100 ) + { + return _ERROR_EMAIL_TOO_LONG; + } + + // begin if: commenter's url is too long + if ( i18n::strlen($comment['userid']) > 100 ) + { + return _ERROR_URL_TOO_LONG; + } + + $comment['timestamp'] = $timestamp; + $comment['host'] = gethostbyaddr(serverVar('REMOTE_ADDR') ); + $comment['ip'] = serverVar('REMOTE_ADDR'); + + // begin if: member is logged in, use that data + if ( $member->isLoggedIn() ) + { + $comment['memberid'] = $member->getID(); + $comment['user'] = ''; + $comment['userid'] = ''; + $comment['email'] = ''; + } + else + { + $comment['memberid'] = 0; + } + + // spam check + $continue = FALSE; + $plugins = array(); + + if ( isset($manager->subscriptions['ValidateForm']) ) + { + $plugins = array_merge($plugins, $manager->subscriptions['ValidateForm']); + } + + if ( isset($manager->subscriptions['PreAddComment']) ) + { + $plugins = array_merge($plugins, $manager->subscriptions['PreAddComment']); + } + + if ( isset($manager->subscriptions['PostAddComment']) ) + { + $plugins = array_merge($plugins, $manager->subscriptions['PostAddComment']); + } + + $plugins = array_unique($plugins); + + while ( list(, $plugin) = each($plugins) ) + { + $p = $manager->getPlugin($plugin); + $continue = $continue || $p->supportsFeature('handleSpam'); + } + + $spamcheck = array( + 'type' => 'comment', + 'body' => $comment['body'], + 'id' => $comment['itemid'], + 'live' => TRUE, + 'return' => $continue + ); + + // begin if: member logged in + if ( $member->isLoggedIn() ) + { + $spamcheck['author'] = $member->displayname; + $spamcheck['email'] = $member->email; + } + // else: public + else + { + $spamcheck['author'] = $comment['user']; + $spamcheck['email'] = $comment['email']; + $spamcheck['url'] = $comment['userid']; + } + + $data = array('spamcheck' => &$spamcheck); + $manager->notify('SpamCheck', $data); + + if ( !$continue && isset($spamcheck['result']) && $spamcheck['result'] == TRUE ) + { + return _ERROR_COMMENTS_SPAM; + } + + // isValidComment returns either "1" or an error message + $isvalid = $this->isValidComment($comment, $spamcheck); + if ( $isvalid != 1 ) + { + return $isvalid; + } + + // begin if: send email to notification address + if ( $settings->getNotifyAddress() && $settings->notifyOnComment() ) + { + + $message = _NOTIFY_NC_MSG . ' ' . $this->itemid . "\n"; + $temp = parse_url($CONF['Self']); + + if ( $temp['scheme'] ) + { + $message .= Link::create_item_link($this->itemid) . "\n\n"; + } + else + { + $tempurl = $settings->getURL(); + + if ( i18n::substr($tempurl, -1) == '/' || i18n::substr($tempurl, -4) == '.php' ) + { + $message .= $tempurl . '?itemid=' . $this->itemid . "\n\n"; + } + else + { + $message .= $tempurl . '/?itemid=' . $this->itemid . "\n\n"; + } + } + + if ( $comment['memberid'] == 0 ) + { + $message .= _NOTIFY_USER . ' ' . $comment['user'] . "\n"; + $message .= _NOTIFY_USERID . ' ' . $comment['userid'] . "\n"; + } + else + { + $message .= _NOTIFY_MEMBER .' ' . $member->getDisplayName() . ' (ID=' . $member->getID() . ")\n"; + } + + $message .= _NOTIFY_HOST . ' ' . $comment['host'] . "\n"; + $message .= _NOTIFY_COMMENT . "\n " . $comment['body'] . "\n"; + $message .= NOTIFICATION::get_mail_footer(); + + $item =& $manager->getItem($this->itemid, 0, 0); + $subject = _NOTIFY_NC_TITLE . ' ' . strip_tags($item['title']) . ' (' . $this->itemid . ')'; + + $from = $member->getNotifyFromMailAddress($comment['email']); + + NOTIFICATION::mail($settings->getNotifyAddress(), $subject, $message, $from, i18n::get_current_charset()); + } + + $comment = Comment::prepare($comment); + + $data = array('comment' => &$comment, 'spamcheck' => &$spamcheck); + $manager->notify('PreAddComment', $data); + + $name = DB::quoteValue($comment['user']); + $url = DB::quoteValue($comment['userid']); + $email = DB::quoteValue($comment['email']); + $body = DB::quoteValue($comment['body']); + $host = DB::quoteValue($comment['host']); + $ip = DB::quoteValue($comment['ip']); + $memberid = intval($comment['memberid']); + $timestamp = DB::formatDateTime($comment['timestamp']); + $itemid = $this->itemid; + + $qSql = 'SELECT COUNT(*) AS result ' + . 'FROM ' . sql_table('comment') + . ' WHERE ' + . 'cmail = ' . $url + . ' AND cmember = ' . $memberid + . ' AND cbody = ' . $body + . ' AND citem = ' . $itemid + . ' AND cblog = ' . $blogid; + $result = (integer) DB::getValue($qSql); + + if ( $result > 0 ) + { + return _ERROR_BADACTION; + } + + $query = sprintf('INSERT INTO %s (cuser, cmail, cemail, cmember, cbody, citem, ctime, chost, cip, cblog) ' + . 'VALUES (%s, %s, %s, %d, %s, %d, %s, %s, %s, %d)' + , sql_table('comment'), $name, $url, $email, $memberid, $body, $itemid, $timestamp, $host, $ip, $blogid); + + DB::execute($query); + + // post add comment + $commentid = DB::getInsertId(); + $data = array('comment' => &$comment, 'commentid' => &$commentid, 'spamcheck' => &$spamcheck); + $manager->notify('PostAddComment', $data); + + // succeeded ! + return TRUE; + } + + /** + * Comments::isValidComment() + * Checks if a comment is valid and call plugins + * that can check if the comment is a spam comment + * + * @param array $comment array with comment elements + * @param array $spamcheck array with spamcheck elements + * @return boolean valid or not + */ + private function isValidComment(&$comment, &$spamcheck) + { + global $member, $manager; + + // check if there exists a item for this date + $item =& $manager->getItem($this->itemid, 0, 0); + + if ( !$item ) + { + return _ERROR_NOSUCHITEM; + } + + if ( $item['closed'] ) + { + return _ERROR_ITEMCLOSED; + } + + // don't allow words that are too long + if ( preg_match('/[a-zA-Z0-9|\.,;:!\?=\/\\\\]{90,90}/', $comment['body']) != 0 ) + { + return _ERROR_COMMENT_LONGWORD; + } + + // check lengths of comment + if ( i18n::strlen($comment['body']) < 3 ) + { + return _ERROR_COMMENT_NOCOMMENT; + } + + if ( i18n::strlen($comment['body']) > 5000 ) + { + return _ERROR_COMMENT_TOOLONG; + } + + // only check username if no member logged in + if ( !$member->isLoggedIn() && (i18n::strlen($comment['user']) < 2) ) + { + return _ERROR_COMMENT_NOUSERNAME; + } + + if ( (i18n::strlen($comment['email']) != 0) && !NOTIFICATION::address_validation(trim($comment['email'])) ) + { + return _ERROR_BADMAILADDRESS; + } + + // let plugins do verification (any plugin which thinks the comment is invalid + // can change 'error' to something other than '1') + $result = 1; + $data = array('type' => 'comment', 'comment' => &$comment, 'error' => &$result, 'spamcheck' => &$spamcheck); + $manager->notify('ValidateForm', $data); + + return $result; + } + } ++>>>>>>> skinnable-master diff --combined nucleus/libs/ITEM.php index 475f6a3,a989ca9..0fce570 --- a/nucleus/libs/ITEM.php +++ b/nucleus/libs/ITEM.php @@@ -1,601 -1,604 +1,1208 @@@ ++<<<<<<< HEAD +itemid = $item_id; + return; + } + + /** + * Item::getitem() + * Returns one item with the specific itemid + * + * @static + * @param int $item_id + * @param bool $allow_draft + * @param bool $allow_future + * @return mixed + */ + static public function getitem($item_id, $allow_draft, $allow_future) + { + global $manager; + + $item_id = (integer) $item_id; + + $query = 'SELECT ' . + 'i.idraft AS draft, ' . + 'i.inumber AS itemid, ' . + 'i.iclosed AS closed, ' . + 'i.ititle AS title, ' . + 'i.ibody AS body, ' . + 'm.mname AS author, ' . + 'i.iauthor AS authorid, ' . + 'i.itime, ' . + 'i.imore AS more, ' . + 'i.ikarmapos AS karmapos, ' . + 'i.ikarmaneg AS karmaneg, ' . + 'i.icat AS catid, ' . + 'i.iblog AS blogid ' . + 'FROM %s AS i, %s AS m, %s AS b ' . + 'WHERE i.inumber = %d ' . + 'AND i.iauthor = m.mnumber ' . + 'AND i.iblog = b.bnumber '; + + $query = sprintf($query, sql_table('item'), sql_table('member'), sql_table('blog'), $item_id); + + if ( !$allow_draft ) + { + $query .= "AND i.idraft = 0 "; + } + + if ( !$allow_future ) + { + $blog =& $manager->getBlog(getBlogIDFromItemID($item_id)); + $query .= 'AND i.itime <= ' . DB::formatDateTime($blog->getCorrectTime()); + } + + $query .= ' LIMIT 1'; + $result = DB::getResult($query); + + if ( $result->rowCount() == 1 ) + { + $aItemInfo = $result->fetch(PDO::FETCH_ASSOC); + $aItemInfo['timestamp'] = strtotime($aItemInfo['itime']); + return $aItemInfo; + } + return 0; + } + + /** + * Item::createFromRequest() + * Tries to create an item from the data in the current request (comes from + * bookmarklet or admin area + * + * @static + * @param void + * @return array (status = added/error/newcategory, message) + * + */ + static public function createFromRequest() + { + global $member, $manager; + + /* + * TODO: these values from user agent should be validated but not implemented yet + */ + $i_author = $member->getID(); + $i_body = postVar('body'); + $i_title = postVar('title'); + $i_more = postVar('more'); + $i_actiontype = postVar('actiontype'); + $i_closed = intPostVar('closed'); + $i_hour = intPostVar('hour'); + $i_minutes = intPostVar('minutes'); + $i_month = intPostVar('month'); + $i_day = intPostVar('day'); + $i_year = intPostVar('year'); + $i_catid = postVar('catid'); + $i_draftid = intPostVar('draftid'); + + if ( !$member->canAddItem($i_catid) ) + { + return array('status' => 'error', 'message' => _ERROR_DISALLOWED); + } + + if ( !in_array($i_actiontype, self::$actiontypes) ) + { + $i_actiontype = 'addnow'; + } + + $i_draft = (integer) ( $i_actiontype == 'adddraft' ); + + if ( !trim($i_body) ) + { + return array('status' => 'error', 'message' => _ERROR_NOEMPTYITEMS); + } + + // create new category if needed + if ( i18n::strpos($i_catid, 'newcat') === 0 ) + { + // get blogid + list($i_blogid) = sscanf($i_catid, "newcat-%d"); + + // create + $blog =& $manager->getBlog($i_blogid); + $i_catid = $blog->createNewCategory(); + + // show error when sth goes wrong + if ( !$i_catid ) + { + return array('status' => 'error','message' => 'Could not create new category'); + } + } + else + { + // force blogid (must be same as category id) + $i_blogid = getBlogIDFromCatID($i_catid); + $blog =& $manager->getBlog($i_blogid); + } + + if ( $i_actiontype == 'addfuture' ) + { + $posttime = mktime($i_hour, $i_minutes, 0, $i_month, $i_day, $i_year); + + // make sure the date is in the future, unless we allow past dates + if ( (!$blog->allowPastPosting()) && ($posttime < $blog->getCorrectTime()) ) + { + $posttime = $blog->getCorrectTime(); + } + } + else + { + if ( !$i_draft ) + { + $posttime = $blog->getCorrectTime(); + } + else + { + $posttime = 0; + } + } + + if ( $posttime > $blog->getCorrectTime() ) + { + $posted = 0; + $blog->setFuturePost(); + } + else + { + $posted = 1; + } + + $itemid = $blog->additem($i_catid, $i_title, $i_body, $i_more, $i_blogid, $i_author, $posttime, $i_closed, $i_draft, $posted); + + //Setting the itemOptions + $aOptions = requestArray('plugoption'); + NucleusPlugin::apply_plugin_options($aOptions, $itemid); + $data = array( + 'context' => 'item', + 'itemid' => $itemid, + 'item' => array( + 'title' => $i_title, + 'body' => $i_body, + 'more' => $i_more, + 'closed' => $i_closed, + 'catid' => $i_catid + ) + ); + + $manager->notify('PostPluginOptionsUpdate', $data); + + if ( $i_draftid > 0 ) + { + // delete permission is checked inside Item::delete() + self::delete($i_draftid); + } + + // success + if ( $i_catid != intRequestVar('catid') ) + { + return array('status' => 'newcategory', 'itemid' => $itemid, 'catid' => $i_catid); + } + + return array('status' => 'added', 'itemid' => $itemid); + } + + /** + * Item::update() + * Updates an item + * + * @static + * @param integer $itemid item id + * @param integer $catid category id + * @param string $title title + * @param string $body body text + * @param string $more more text + * @param boolean $closed closed or not + * @param boolean $wasdraft previously draft or not + * @param boolean $publish published or not + * @param timestamp $timestamp timestamp + * @return void + */ + static public function update($itemid, $catid, $title, $body, $more, $closed, $wasdraft, $publish, $timestamp = 0) + { + global $manager; + + $itemid = (integer) $itemid; + $closed = (boolean) $closed; + + // get destination blogid + $new_blogid = getBlogIDFromCatID($catid); + $old_blogid = getBlogIDFromItemID($itemid); + + // move will be done on end of method + $moveNeeded = 0; + if ( $new_blogid != $old_blogid ) + { + $moveNeeded = 1; + } + + $blog =& $manager->getBlog($new_blogid); + + // begin if: convert line breaks to
+ if ( $blog->convertBreaks() ) + { + $body = addBreaks($body); + $more = addBreaks($more); + } + + // call plugins + $data = array( + 'itemid' => $itemid, + 'title' => &$title, + 'body' => &$body, + 'more' => &$more, + 'blog' => &$blog, + 'closed' => &$closed, + 'catid' => &$catid + ); + $manager->notify('PreUpdateItem', $data); + + // update item itself + $query = 'UPDATE ' . sql_table('item') + . ' SET' + . ' ibody = ' . DB::quoteValue($body) . ',' + . ' ititle = ' . DB::quoteValue($title) . ',' + . ' imore = ' . DB::quoteValue($more) . ',' + . ' iclosed = ' . intval($closed) . ',' + . ' icat = ' . intval($catid); + + // if we received an updated timestamp that is in the past, but past posting is not allowed, + // reject that date change (timestamp = 0 will make sure the current date is kept) + if ( (!$blog->allowPastPosting()) && ($timestamp < $blog->getCorrectTime()) ) + { + $timestamp = 0; + } + + // begin if: post is in the future + if ( $timestamp > $blog->getCorrectTime(time()) ) + { + $isFuture = 1; + $query .= ', iposted = 0'; + } + else + { + $isFuture = 0; + $query .= ', iposted = 1'; + } + + if ( $wasdraft && $publish ) + { + // set timestamp to current date only if it's not a future item + // draft items have timestamp == 0 + // don't allow timestamps in the past (unless otherwise defined in blogsettings) + $query .= ', idraft = 0'; + + if ( $timestamp == 0 ) + { + $timestamp = $blog->getCorrectTime(); + } + + // send new item notification + if ( !$isFuture && $blog->getNotifyAddress() && $blog->notifyOnNewItem() ) + { + $blog->sendNewItemNotification($itemid, $title, $body); + } + } + + // save back to drafts + if ( !$wasdraft && !$publish ) + { + $query .= ', idraft = 1'; + // set timestamp back to zero for a draft + $query .= ', itime = ' . DB::formatDateTime($timestamp); + } + + // update timestamp when needed + if ( $timestamp != 0 ) + { + $query .= ', itime = ' . DB::formatDateTime($timestamp); + } + + // make sure the correct item is updated + $query .= ' WHERE inumber = ' . $itemid; + + // off we go! + DB::execute($query); + + $manager->notify('PostUpdateItem', array('itemid' => $itemid)); + + // when needed, move item and comments to new blog + if ( $moveNeeded ) + { + self::move($itemid, $catid); + } + + //update the itemOptions + $aOptions = requestArray('plugoption'); + NucleusPlugin::apply_plugin_options($aOptions); + $data = array( + 'context' => 'item', + 'itemid' => $itemid, + 'item' => array( + 'title' => $title, + 'body' => $body, + 'more' => $more, + 'closed' => $closed, + 'catid' => $catid + ) + ); + $manager->notify('PostPluginOptionsUpdate', $data); + return; + } + + /** + * Item::move() + * Move an item to another blog (no checks) + * + * @static + * @param integer $itemid + * @param integer $new_catid + * @return void + */ + static public function move($itemid, $new_catid) + { + global $manager; + + $itemid = (integer) $itemid; + $new_catid = (integer) $new_catid; + $new_blogid = getBlogIDFromCatID($new_catid); + + $data = array( + 'itemid' => $itemid, + 'destblogid' => $new_blogid, + 'destcatid' => $new_catid + ); + $manager->notify('PreMoveItem', $data); + + // update item table + $query = "UPDATE %s SET iblog=%d, icat=%d WHERE inumber=%d"; + $query = sprintf($query, sql_table('item'), $new_blogid, $new_catid, $itemid); + DB::execute($query); + + // update comments + $query = "UPDATE %s SET cblog=%d WHERE citem=%d"; + $query = sprintf($query, sql_table('comment'), $new_blogid, $itemid); + DB::execute($query); + + $data = array( + 'itemid' => $itemid, + 'destblogid' => $new_blogid, + 'destcatid' => $new_catid + ); + $manager->notify('PostMoveItem', $data); + return; + } + + /** + * Item::delete() + * Deletes an item + * + * @param integer $itemid + * @return void + */ + static public function delete($itemid) + { + global $manager, $member; + + $itemid = (integer) $itemid; + + // check permission + if ( !$member->canAlterItem($itemid) ) + { + return 1; + } + + $manager->notify('PreDeleteItem', array('itemid' => $itemid)); + + // delete item + $query = "DELETE FROM %s WHERE inumber=%d;"; + $query = sprintf($query, sql_table('item'), $itemid); + DB::execute($query); + + // delete the comments associated with the item + $query = "DELETE FROM %s WHERE citem=%d;"; + $query = sprintf($query, sql_table('comment'), $itemid); + DB::execute($query); + + // delete all associated plugin options + NucleusPlugin::delete_option_values('item', $itemid); + + $manager->notify('PostDeleteItem', array('itemid' => $itemid)); + + return 0; + } + + /** + * Item::exists() + * Returns true if there is an item with the given ID + * + * @static + * @param integer $itemid + * @param boolean $future + * @param boolean $draft + * @return boolean exists or not + */ + static public function exists($itemid, $future, $draft) + { + global $manager; + + $itemid = (integer) $itemid; + + $query = 'SELECT * FROM %s WHERE inumber=%d'; + $query = sprintf($query, sql_table('item'), $itemid); + + if ( !$future ) + { + $blogid = getBlogIDFromItemID($itemid); + if ( !$blogid ) + { + return 0; + } + $blog =& $manager->getBlog($blogid); + $query .= ' AND itime<=' . DB::formatDateTime($blog->getCorrectTime()); + } + + if ( !$draft ) + { + $query .= ' AND idraft=0'; + } + + $result = DB::getResult($query); + return ( $result->rowCount() != 0 ); + } + + /** + * Item::createDraftFromRequest() + * Tries to create an draft from the data + * in the current request (comes from bookmarklet or admin area) + * Used by xmlHTTPRequest AutoDraft + * + * Returns an array with status info: + * status = 'added', 'error', 'newcategory' + * + * @static + * @param void + * @return array (status = added/error/newcategory, message) + */ + static public function createDraftFromRequest() + { + global $member, $manager; + + /* + * TODO: these values from user agent should be validated but not implemented yet + */ + $i_author = $member->getID(); + $i_body = postVar('body'); + $i_title = postVar('title'); + $i_more = postVar('more'); + $i_closed = intPostVar('closed'); + $i_catid = postVar('catid'); + $i_draft = 1; + $type = postVar('type'); + $i_draftid = intPostVar('draftid'); + + if ( $type == 'edit' ) + { + $itemid = intPostVar('itemid'); + $i_blogid = getBlogIDFromItemID($itemid); + } + else + { + $i_blogid = intPostVar('blogid'); + } + + if ( !$member->canAddItem($i_catid) ) + { + return array('status' => 'error', 'message' => _ERROR_DISALLOWED); + } + + if ( !trim($i_body) ) + { + return array('status' => 'error', 'message' => _ERROR_NOEMPTYITEMS); + } + + // create new category if needed + if ( i18n::strpos($i_catid,'newcat') === 0 ) + { + // Set in default category + $blog =& $manager->getBlog($i_blogid); + $i_catid = $blog->getDefaultCategory(); + } + else + { + // force blogid (must be same as category id) + $i_blogid = getBlogIDFromCatID($i_catid); + $blog =& $manager->getBlog($i_blogid); + } + + $posttime = 0; + + if ( $i_draftid > 0 ) + { + self::update($i_draftid, $i_catid, $i_title, $i_body, $i_more, $i_closed, 1, 0, 0); + $itemid = $i_draftid; + } + else + { + $itemid = $blog->additem($i_catid, $i_title, $i_body, $i_more, $i_blogid, $i_author, $posttime, $i_closed, $i_draft); + } + + return array('status' => 'added', 'draftid' => $itemid); + } +} ++======= + itemid = $item_id; + return; + } + + /** + * Item::getitem() + * Returns one item with the specific itemid + * + * @static + * @param int $item_id + * @param bool $allow_draft + * @param bool $allow_future + * @return mixed + */ + static public function getitem($item_id, $allow_draft, $allow_future) + { + global $manager; + + $item_id = (integer) $item_id; + + $query = 'SELECT ' . + 'i.idraft AS draft, ' . + 'i.inumber AS itemid, ' . + 'i.iclosed AS closed, ' . + 'i.ititle AS title, ' . + 'i.ibody AS body, ' . + 'm.mname AS author, ' . + 'i.iauthor AS authorid, ' . + 'i.itime, ' . + 'i.imore AS more, ' . + 'i.ikarmapos AS karmapos, ' . + 'i.ikarmaneg AS karmaneg, ' . + 'i.icat AS catid, ' . + 'i.iblog AS blogid ' . + 'FROM %s AS i, %s AS m, %s AS b ' . + 'WHERE i.inumber = %d ' . + 'AND i.iauthor = m.mnumber ' . + 'AND i.iblog = b.bnumber '; + + $query = sprintf($query, sql_table('item'), sql_table('member'), sql_table('blog'), $item_id); + + if ( !$allow_draft ) + { + $query .= "AND i.idraft = 0 "; + } + + if ( !$allow_future ) + { + $blog =& $manager->getBlog(getBlogIDFromItemID($item_id)); + $query .= 'AND i.itime <= ' . DB::formatDateTime($blog->getCorrectTime()); + } + + $query .= ' LIMIT 1'; + $result = DB::getResult($query); + + if ( $result->rowCount() != 1 ) + { + return 0; + } + + $aItemInfo = $result->fetch(PDO::FETCH_ASSOC); + $aItemInfo['timestamp'] = strtotime($aItemInfo['itime']); + return $aItemInfo; + } + + /** + * Item::createFromRequest() + * Tries to create an item from the data in the current request (comes from + * bookmarklet or admin area + * + * @static + * @param void + * @return array (status = added/error/newcategory, message) + * + */ + static public function createFromRequest() + { + global $member, $manager; + + /* + * TODO: these values from user agent should be validated but not implemented yet + */ + $i_author = $member->getID(); + $i_body = postVar('body'); + $i_title = postVar('title'); + $i_more = postVar('more'); + $i_actiontype = postVar('actiontype'); + $i_closed = intPostVar('closed'); + $i_hour = intPostVar('hour'); + $i_minutes = intPostVar('minutes'); + $i_month = intPostVar('month'); + $i_day = intPostVar('day'); + $i_year = intPostVar('year'); + $i_catid = postVar('catid'); + $i_draftid = intPostVar('draftid'); + + if ( !$member->canAddItem($i_catid) ) + { + return array('status' => 'error', 'message' => _ERROR_DISALLOWED); + } + + if ( !in_array($i_actiontype, self::$actiontypes) ) + { + $i_actiontype = 'addnow'; + } + + $i_draft = (integer) ( $i_actiontype == 'adddraft' ); + + if ( !trim($i_body) ) + { + return array('status' => 'error', 'message' => _ERROR_NOEMPTYITEMS); + } + + // create new category if needed + if ( i18n::strpos($i_catid, 'newcat') === 0 ) + { + // get blogid + list($i_blogid) = sscanf($i_catid, "newcat-%d"); + + // create + $blog =& $manager->getBlog($i_blogid); + $i_catid = $blog->createNewCategory(); + + // show error when sth goes wrong + if ( !$i_catid ) + { + return array('status' => 'error','message' => 'Could not create new category'); + } + } + else + { + // force blogid (must be same as category id) + $i_blogid = getBlogIDFromCatID($i_catid); + $blog =& $manager->getBlog($i_blogid); + } + + if ( $i_actiontype == 'addfuture' ) + { + $posttime = mktime($i_hour, $i_minutes, 0, $i_month, $i_day, $i_year); + + // make sure the date is in the future, unless we allow past dates + if ( (!$blog->allowPastPosting()) && ($posttime < $blog->getCorrectTime()) ) + { + $posttime = $blog->getCorrectTime(); + } + } + else + { + if ( !$i_draft ) + { + $posttime = $blog->getCorrectTime(); + } + else + { + $posttime = 0; + } + } + + if ( $posttime > $blog->getCorrectTime() ) + { + $posted = 0; + $blog->setFuturePost(); + } + else + { + $posted = 1; + } + + $itemid = $blog->additem($i_catid, $i_title, $i_body, $i_more, $i_blogid, $i_author, $posttime, $i_closed, $i_draft, $posted); + + //Setting the itemOptions + $aOptions = requestArray('plugoption'); + NucleusPlugin::apply_plugin_options($aOptions, $itemid); + $data = array( + 'context' => 'item', + 'itemid' => $itemid, + 'item' => array( + 'title' => $i_title, + 'body' => $i_body, + 'more' => $i_more, + 'closed' => $i_closed, + 'catid' => $i_catid + ) + ); + + $manager->notify('PostPluginOptionsUpdate', $data); + + if ( $i_draftid > 0 ) + { + // delete permission is checked inside Item::delete() + self::delete($i_draftid); + } + + // success + if ( $i_catid != intRequestVar('catid') ) + { + return array('status' => 'newcategory', 'itemid' => $itemid, 'catid' => $i_catid); + } + + return array('status' => 'added', 'itemid' => $itemid); + } + + /** + * Item::update() + * Updates an item + * + * @static + * @param integer $itemid item id + * @param integer $catid category id + * @param string $title title + * @param string $body body text + * @param string $more more text + * @param boolean $closed closed or not + * @param boolean $wasdraft previously draft or not + * @param boolean $publish published or not + * @param timestamp $timestamp timestamp + * @return void + */ + static public function update($itemid, $catid, $title, $body, $more, $closed, $wasdraft, $publish, $timestamp = 0) + { + global $manager; + + $itemid = (integer) $itemid; + $closed = (boolean) $closed; + + // get destination blogid + $new_blogid = getBlogIDFromCatID($catid); + $old_blogid = getBlogIDFromItemID($itemid); + + // move will be done on end of method + $moveNeeded = 0; + if ( $new_blogid != $old_blogid ) + { + $moveNeeded = 1; + } + + $blog =& $manager->getBlog($new_blogid); + + // begin if: convert line breaks to
+ if ( $blog->convertBreaks() ) + { + $body = addBreaks($body); + $more = addBreaks($more); + } + + // call plugins + $data = array( + 'itemid' => $itemid, + 'title' => &$title, + 'body' => &$body, + 'more' => &$more, + 'blog' => &$blog, + 'closed' => &$closed, + 'catid' => &$catid + ); + $manager->notify('PreUpdateItem', $data); + + // update item itself + $query = 'UPDATE ' . sql_table('item') + . ' SET' + . ' ibody = ' . DB::quoteValue($body) . ',' + . ' ititle = ' . DB::quoteValue($title) . ',' + . ' imore = ' . DB::quoteValue($more) . ',' + . ' iclosed = ' . intval($closed) . ',' + . ' icat = ' . intval($catid); + + // if we received an updated timestamp that is in the past, but past posting is not allowed, + // reject that date change (timestamp = 0 will make sure the current date is kept) + if ( (!$blog->allowPastPosting()) && ($timestamp < $blog->getCorrectTime()) ) + { + $timestamp = 0; + } + + // begin if: post is in the future + if ( $timestamp > $blog->getCorrectTime(time()) ) + { + $isFuture = 1; + $query .= ', iposted = 0'; + } + else + { + $isFuture = 0; + $query .= ', iposted = 1'; + } + + if ( $wasdraft && $publish ) + { + // set timestamp to current date only if it's not a future item + // draft items have timestamp == 0 + // don't allow timestamps in the past (unless otherwise defined in blogsettings) + $query .= ', idraft = 0'; + + if ( $timestamp == 0 ) + { + $timestamp = $blog->getCorrectTime(); + } + + // send new item notification + if ( !$isFuture && $blog->getNotifyAddress() && $blog->notifyOnNewItem() ) + { + $blog->sendNewItemNotification($itemid, $title, $body); + } + } + + // save back to drafts + if ( !$wasdraft && !$publish ) + { + $query .= ', idraft = 1'; + // set timestamp back to zero for a draft + $query .= ', itime = ' . DB::formatDateTime($timestamp); + } + + // update timestamp when needed + if ( $timestamp != 0 ) + { + $query .= ', itime = ' . DB::formatDateTime($timestamp); + } + + // make sure the correct item is updated + $query .= ' WHERE inumber = ' . $itemid; + + // off we go! + DB::execute($query); + + $data = array('itemid' => $itemid); + $manager->notify('PostUpdateItem', $data); + + // when needed, move item and comments to new blog + if ( $moveNeeded ) + { + self::move($itemid, $catid); + } + + //update the itemOptions + $aOptions = requestArray('plugoption'); + NucleusPlugin::apply_plugin_options($aOptions); + $data = array( + 'context' => 'item', + 'itemid' => $itemid, + 'item' => array( + 'title' => $title, + 'body' => $body, + 'more' => $more, + 'closed' => $closed, + 'catid' => $catid + ) + ); + $manager->notify('PostPluginOptionsUpdate', $data); + return; + } + + /** + * Item::move() + * Move an item to another blog (no checks) + * + * @static + * @param integer $itemid + * @param integer $new_catid + * @return void + */ + static public function move($itemid, $new_catid) + { + global $manager; + + $itemid = (integer) $itemid; + $new_catid = (integer) $new_catid; + $new_blogid = getBlogIDFromCatID($new_catid); + + $data = array( + 'itemid' => $itemid, + 'destblogid' => $new_blogid, + 'destcatid' => $new_catid + ); + $manager->notify('PreMoveItem', $data); + + // update item table + $query = "UPDATE %s SET iblog=%d, icat=%d WHERE inumber=%d"; + $query = sprintf($query, sql_table('item'), $new_blogid, $new_catid, $itemid); + DB::execute($query); + + // update comments + $query = "UPDATE %s SET cblog=%d WHERE citem=%d"; + $query = sprintf($query, sql_table('comment'), $new_blogid, $itemid); + DB::execute($query); + + $data = array( + 'itemid' => $itemid, + 'destblogid' => $new_blogid, + 'destcatid' => $new_catid + ); + $manager->notify('PostMoveItem', $data); + return; + } + + /** + * Item::delete() + * Deletes an item + * + * @param integer $itemid + * @return void + */ + static public function delete($itemid) + { + global $manager, $member; + + $itemid = (integer) $itemid; + + // check permission + if ( !$member->canAlterItem($itemid) ) + { + return 1; + } + + $data = array('itemid' => $itemid); + $manager->notify('PreDeleteItem', $data); + + // delete item + $query = "DELETE FROM %s WHERE inumber=%d;"; + $query = sprintf($query, sql_table('item'), $itemid); + DB::execute($query); + + // delete the comments associated with the item + $query = "DELETE FROM %s WHERE citem=%d;"; + $query = sprintf($query, sql_table('comment'), $itemid); + DB::execute($query); + + // delete all associated plugin options + NucleusPlugin::delete_option_values('item', $itemid); + + $manager->notify('PostDeleteItem', $data); + + return 0; + } + + /** + * Item::exists() + * Returns true if there is an item with the given ID + * + * @static + * @param integer $itemid + * @param boolean $future + * @param boolean $draft + * @return boolean exists or not + */ + static public function exists($itemid, $future, $draft) + { + global $manager; + + $itemid = (integer) $itemid; + + $query = 'SELECT * FROM %s WHERE inumber=%d'; + $query = sprintf($query, sql_table('item'), $itemid); + + if ( !$future ) + { + $blogid = getBlogIDFromItemID($itemid); + if ( !$blogid ) + { + return 0; + } + $blog =& $manager->getBlog($blogid); + $query .= ' AND itime<=' . DB::formatDateTime($blog->getCorrectTime()); + } + + if ( !$draft ) + { + $query .= ' AND idraft=0'; + } + + $result = DB::getResult($query); + return ( $result->rowCount() != 0 ); + } + + /** + * Item::createDraftFromRequest() + * Tries to create an draft from the data + * in the current request (comes from bookmarklet or admin area) + * Used by xmlHTTPRequest AutoDraft + * + * Returns an array with status info: + * status = 'added', 'error', 'newcategory' + * + * @static + * @param void + * @return array (status = added/error/newcategory, message) + */ + static public function createDraftFromRequest() + { + global $member, $manager; + + /* + * TODO: these values from user agent should be validated but not implemented yet + */ + $i_author = $member->getID(); + $i_body = postVar('body'); + $i_title = postVar('title'); + $i_more = postVar('more'); + $i_closed = intPostVar('closed'); + $i_catid = postVar('catid'); + $i_draft = 1; + $type = postVar('type'); + $i_draftid = intPostVar('draftid'); + + if ( $type == 'edit' ) + { + $itemid = intPostVar('itemid'); + $i_blogid = getBlogIDFromItemID($itemid); + } + else + { + $i_blogid = intPostVar('blogid'); + } + + if ( !$member->canAddItem($i_catid) ) + { + return array('status' => 'error', 'message' => _ERROR_DISALLOWED); + } + + if ( !trim($i_body) ) + { + return array('status' => 'error', 'message' => _ERROR_NOEMPTYITEMS); + } + + // create new category if needed + if ( i18n::strpos($i_catid,'newcat') === 0 ) + { + // Set in default category + $blog =& $manager->getBlog($i_blogid); + $i_catid = $blog->getDefaultCategory(); + } + else + { + // force blogid (must be same as category id) + $i_blogid = getBlogIDFromCatID($i_catid); + $blog =& $manager->getBlog($i_blogid); + } + + $posttime = 0; + + if ( $i_draftid > 0 ) + { + self::update($i_draftid, $i_catid, $i_title, $i_body, $i_more, $i_closed, 1, 0, 0); + $itemid = $i_draftid; + } + else + { + $itemid = $blog->additem($i_catid, $i_title, $i_body, $i_more, $i_blogid, $i_author, $posttime, $i_closed, $i_draft); + } + + return array('status' => 'added', 'draftid' => $itemid); + } + } ++>>>>>>> skinnable-master diff --combined nucleus/libs/ITEMACTIONS.php index 9aa96d4,2306fa3..7db9281 --- a/nucleus/libs/ITEMACTIONS.php +++ b/nucleus/libs/ITEMACTIONS.php @@@ -14,7 -14,7 +14,11 @@@ * * @license http://nucleuscms.org/license.txt GNU General Public License * @copyright Copyright (C) 2002-2009 The Nucleus Group ++<<<<<<< HEAD + * @version $Id: ITEMACTIONS.php 1757 2012-04-15 09:02:32Z sakamocchi $ ++======= + * @version $Id: ITEMACTIONS.php 1886 2012-06-17 08:27:27Z sakamocchi $ ++>>>>>>> skinnable-master */ class ItemActions extends BaseActions { @@@ -101,7 -101,7 +105,11 @@@ /* actions defined in BodyAction class */ 'image', 'media', ++<<<<<<< HEAD + 'popup', ++======= + 'popup' ++>>>>>>> skinnable-master ); /** @@@ -753,9 -753,10 +761,16 @@@ array_shift($params); // add item reference (array_unshift didn't work) ++<<<<<<< HEAD + $params = array_merge(array(&$this->currentItem),$params); + + call_user_func_array(array(&$plugin,'doTemplateVar'), $params); ++======= + $target = array(&$this->currentItem); + $params = array_merge($target,$params); + + call_user_func_array(array($plugin,'doTemplateVar'), $params); ++>>>>>>> skinnable-master return; } @@@ -817,7 -818,8 +832,12 @@@ $handler->setCurrentItem($this->currentItem); $parser = new Parser($handler); ++<<<<<<< HEAD + $parser->parse($handler->highlight($data)); ++======= + $highlight = $handler->highlight($data); + $parser->parse($highlight); ++>>>>>>> skinnable-master return; } @@@ -847,8 -849,9 +867,14 @@@ $condition = ($blog && ($blog->getSetting($name) == $value)); break; case 'itemblogsetting': ++<<<<<<< HEAD + $b =& $manager->getBlog(getBlogIDFromItemID($this->currentItem['itemid'])); + $condition = ($b && ($b->getSetting($name) == $value)); ++======= + $item =& $manager->getItem($this->currentItem['itemid'], 1, 1); + $t_blog =& $manager->getBlog($item['blogid']); + $condition = ($t_blog && ($t_blog->getSetting($name) == $value)); ++>>>>>>> skinnable-master break; case 'loggedin': $condition = $member->isLoggedIn(); @@@ -920,8 -923,6 +946,11 @@@ { global $member, $manager; ++<<<<<<< HEAD + $b =& $manager->getBlog(getBlogIDFromItemID($this->currentItem['itemid'])); + ++======= ++>>>>>>> skinnable-master // when no parameter is defined, just check if author is current visitor if ( ($key != 'isadmin' && $key != 'name') || ($key == 'name' && $value == '') ) { @@@ -941,14 -942,12 +970,23 @@@ // check if author is admin if ( ($key == 'isadmin') ) { ++<<<<<<< HEAD + $aid = intval($this->currentItem['authorid']); + $blogid = intval($b->getID()); + $amember =& $manager->getMember($aid); + if ( $amember->isAdmin() ) + { + return TRUE; + } + return (boolean) $amember->isBlogAdmin($blogid); ++======= + $i_author =& $manager->getMember($this->currentItem['authorid']); + if ( $i_author->isAdmin() ) + { + return TRUE; + } + return (boolean) $i_author->isBlogAdmin($this->currentItem['blogid']); ++>>>>>>> skinnable-master } return FALSE; @@@ -966,12 -965,12 +1004,20 @@@ { global $catid, $manager; ++<<<<<<< HEAD + $b =& $manager->getBlog(getBlogIDFromItemID($this->currentItem['itemid'])); ++======= + $blog =& $manager->getBlog($this->currentItem['blogid']); ++>>>>>>> skinnable-master // when no parameter is defined, just check if a category is selected if ( ($key != 'catname' && $key != 'catid') || ($value == '') ) { ++<<<<<<< HEAD + return (boolean) $b->isValidCategory($catid); ++======= + return (boolean) $blog->isValidCategory($catid); ++>>>>>>> skinnable-master } $icatid = $this->currentItem['catid']; @@@ -979,17 -978,17 +1025,28 @@@ // check category name if ( $key == 'catname' ) { ++<<<<<<< HEAD + $value = $b->getCategoryIdFromName($value); + if ( $value == $icatid ) + { + return (boolean) $b->isValidCategory($icatid); ++======= + $value = $blog->getCategoryIdFromName($value); + if ( $value == $icatid ) + { + return (boolean) $blog->isValidCategory($icatid); ++>>>>>>> skinnable-master } } // check category id if ( ($key == 'catid') && ($value == $icatid) ) { ++<<<<<<< HEAD + return (boolean) $b->isValidCategory($icatid); ++======= + return (boolean) $blog->isValidCategory($icatid); ++>>>>>>> skinnable-master } return FALSE; } @@@ -1123,6 -1122,6 +1180,10 @@@ $params = func_get_args(); array_shift($params); ++<<<<<<< HEAD + return (boolean) call_user_func_array(array(&$plugin, 'doIf'), $params); ++======= + return (boolean) call_user_func_array(array($plugin, 'doIf'), $params); ++>>>>>>> skinnable-master } } diff --combined nucleus/libs/KARMA.php index 1c7dcb4,6370305..5471c04 --- a/nucleus/libs/KARMA.php +++ b/nucleus/libs/KARMA.php @@@ -1,116 -1,116 +1,235 @@@ ++<<<<<<< HEAD +itemid = intval($itemid); + + // have we read the karma info yet? + $this->inforead = intval($initread); + + // number of positive and negative votes + $this->karmapos = intval($initpos); + $this->karmaneg = intval($initneg); + } + + function getNbPosVotes() { + if (!$this->inforead) $this->readFromDatabase(); + return $this->karmapos; + } + function getNbNegVotes() { + if (!$this->inforead) $this->readFromDatabase(); + return $this->karmaneg; + } + function getNbOfVotes() { + if (!$this->inforead) $this->readFromDatabase(); + return ($this->karmapos + $this->karmaneg); + } + function getTotalScore() { + if (!$this->inforead) $this->readFromDatabase(); + return ($this->karmapos - $this->karmaneg); + } + + function setNbPosVotes($val) { + $this->karmapos = intval($val); + } + function setNbNegVotes($val) { + $this->karmaneg = intval($val); + } + + + // adds a positive vote + function votePositive() { + $newKarma = $this->getNbPosVotes() + 1; + $this->setNbPosVotes($newKarma); + $this->writeToDatabase(); + $this->saveIP(); + } + + // adds a negative vote + function voteNegative() { + $newKarma = $this->getNbNegVotes() + 1; + $this->setNbNegVotes($newKarma); + $this->writeToDatabase(); + $this->saveIP(); + } + + + + // these methods shouldn't be called directly + function readFromDatabase() { + $query = 'SELECT ikarmapos, ikarmaneg FROM '.sql_table('item').' WHERE inumber=' . $this->itemid; + $res = DB::getRow($query); + + $this->karmapos = $res['ikarmapos']; + $this->karmaneg = $res['ikarmaneg']; + $this->inforead = 1; + } + + + function writeToDatabase() { + $query = 'UPDATE '.sql_table('item').' SET ikarmapos=' . $this->karmapos . ', ikarmaneg='.$this->karmaneg.' WHERE inumber=' . $this->itemid; + DB::execute($query); + } + + // checks if a vote is still allowed for an IP + function isVoteAllowed($ip) { + $query = 'SELECT * FROM '.sql_table('karma')." WHERE itemid={$this->itemid} and ip=". DB::quoteValue($ip); + $res = DB::getResult($query); + return ($res->rowCount() == 0); + } + + // save IP in database so no multiple votes are possible + function saveIP() { + $query = 'INSERT INTO ' . sql_table('karma') .' (itemid, ip) VALUES (' . $this->itemid . ','. DB::quoteValue(serverVar('REMOTE_ADDR')) .')'; + DB::execute($query); + } +} + +?> ++======= + itemid = intval($itemid); + + // have we read the karma info yet? + $this->inforead = intval($initread); + + // number of positive and negative votes + $this->karmapos = intval($initpos); + $this->karmaneg = intval($initneg); + } + + function getNbPosVotes() { + if (!$this->inforead) $this->readFromDatabase(); + return $this->karmapos; + } + function getNbNegVotes() { + if (!$this->inforead) $this->readFromDatabase(); + return $this->karmaneg; + } + function getNbOfVotes() { + if (!$this->inforead) $this->readFromDatabase(); + return ($this->karmapos + $this->karmaneg); + } + function getTotalScore() { + if (!$this->inforead) $this->readFromDatabase(); + return ($this->karmapos - $this->karmaneg); + } + + function setNbPosVotes($val) { + $this->karmapos = intval($val); + } + function setNbNegVotes($val) { + $this->karmaneg = intval($val); + } + + + // adds a positive vote + function votePositive() { + $newKarma = $this->getNbPosVotes() + 1; + $this->setNbPosVotes($newKarma); + $this->writeToDatabase(); + $this->saveIP(); + } + + // adds a negative vote + function voteNegative() { + $newKarma = $this->getNbNegVotes() + 1; + $this->setNbNegVotes($newKarma); + $this->writeToDatabase(); + $this->saveIP(); + } + + + + // these methods shouldn't be called directly + function readFromDatabase() { + $query = 'SELECT ikarmapos, ikarmaneg FROM '.sql_table('item').' WHERE inumber=' . $this->itemid; + $res = DB::getRow($query); + + $this->karmapos = $res['ikarmapos']; + $this->karmaneg = $res['ikarmaneg']; + $this->inforead = 1; + } + + + function writeToDatabase() { + $query = 'UPDATE '.sql_table('item').' SET ikarmapos=' . $this->karmapos . ', ikarmaneg='.$this->karmaneg.' WHERE inumber=' . $this->itemid; + DB::execute($query); + } + + // checks if a vote is still allowed for an IP + function isVoteAllowed($ip) { + $query = 'SELECT * FROM '.sql_table('karma')." WHERE itemid={$this->itemid} and ip=". DB::quoteValue($ip); + $res = DB::getResult($query); + return ($res->rowCount() == 0); + } + + // save IP in database so no multiple votes are possible + function saveIP() { + $query = 'INSERT INTO ' . sql_table('karma') .' (itemid, ip) VALUES (' . $this->itemid . ','. DB::quoteValue(serverVar('REMOTE_ADDR')) .')'; + DB::execute($query); + } + } + -?> ++?> ++>>>>>>> skinnable-master diff --combined nucleus/libs/MANAGER.php index 737899a,fa45dfa..d41bd3d --- a/nucleus/libs/MANAGER.php +++ b/nucleus/libs/MANAGER.php @@@ -1,785 -1,787 +1,1575 @@@ ++<<<<<<< HEAD + $name) + */ + private $cachedInfo; + + /** + * The plugin subscriptionlist + * + * The subcription array has the following structure + * $subscriptions[$EventName] = array containing names of plugin classes to be + * notified when that event happens + * + * NOTE: this is referred by Comments::addComment() for spamcheck API + * TODO: we should add new methods to get this + */ + public $subscriptions; + + /** + * Ticket functions. These are uses by the admin area to make it impossible to simulate certain GET/POST + * requests. tickets are user specific + */ + private $currentRequestTicket = ''; + + /** + * Returns the only instance of this class. Creates the instance if it + * does not yet exists. Users should use this function as + * $manager =& Manager::instance(); to get a reference to the object + * instead of a copy + */ + public function &instance() + { + static $instance = array(); + if ( empty($instance) ) + { + $instance[0] = new Manager(); + } + return $instance[0]; + } + + /** + * The constructor of this class initializes the object caches + */ + public function __construct() + { + $this->items = array(); + $this->blogs = array(); + $this->plugins = array(); + $this->karma = array(); + $this->parserPrefs = array(); + $this->cachedInfo = array(); + return; + } + + /** + * Returns the requested item object. If it is not in the cache, it will + * first be loaded and then placed in the cache. + * Intended use: $item =& $manager->getItem(1234) + */ + public function &getItem($itemid, $allowdraft, $allowfuture) + { + $item =& $this->items[$itemid]; + + // check the draft and future rules if the item was already cached + if ( $item ) + { + if ( (!$allowdraft) && ($item['draft']) ) + { + return 0; + } + + $blog =& $this->getBlog(getBlogIDFromItemID($itemid)); + + if ( (!$allowfuture) && ($item['timestamp'] > $blog->getCorrectTime()) ) + { + return 0; + } + } + + if ( !$item ) + { + // load class if needed + $this->loadClass('ITEM'); + // load item object + $item = Item::getitem($itemid, $allowdraft, $allowfuture); + $this->items[$itemid] = $item; + } + return $item; + } + + /** + * Loads a class if it has not yet been loaded + */ + public function loadClass($name) + { + $this->_loadClass($name, $name . '.php'); + return; + } + + /** + * Checks if an item exists + */ + public function existsItem($id,$future,$draft) + { + $this->_loadClass('ITEM','ITEM.php'); + return Item::exists($id,$future,$draft); + } + + /** + * Checks if a category exists + */ + public function existsCategory($id) + { + return (DB::getValue('SELECT COUNT(*) as result FROM '.sql_table('category').' WHERE catid='.intval($id)) > 0); + } + + /** + * Returns the blog object for a given blogid + */ + public function &getBlog($blogid) + { + $blog =& $this->blogs[$blogid]; + + if ( !$blog ) + { + // load class if needed + $this->_loadClass('BLOG','BLOG.php'); + // load blog object + $blog = new Blog($blogid); + $this->blogs[$blogid] =& $blog; + } + return $blog; + } + + /** + * Checks if a blog exists + */ + public function existsBlog($name) + { + $this->_loadClass('BLOG','BLOG.php'); + return Blog::exists($name); + } + + /** + * Checks if a blog id exists + */ + public function existsBlogID($id) + { + $this->_loadClass('BLOG','BLOG.php'); + return Blog::existsID($id); + } + + /** + * Returns a previously read template + */ + public function &getTemplate($templateName) + { + $template =& $this->templates[$templateName]; + + if ( !$template ) + { + $template = Template::read($templateName); + $this->templates[$templateName] =& $template; + } + return $template; + } + + /** + * Returns a KARMA object (karma votes) + */ + public function &getKarma($itemid) + { + $karma =& $this->karma[$itemid]; + + if ( !$karma ) + { + // load class if needed + $this->_loadClass('KARMA','KARMA.php'); + // create KARMA object + $karma = new Karma($itemid); + $this->karma[$itemid] =& $karma; + } + return $karma; + } + + /** + * Returns a MEMBER object + */ + public function &getMember($memberid) + { + $mem =& $this->members[$memberid]; + + if ( !$mem ) + { + // load class if needed + $this->_loadClass('MEMBER','MEMBER.php'); + // create MEMBER object + $mem =& Member::createFromID($memberid); + $this->members[$memberid] =& $mem; + } + return $mem; + } + + /** + * Set the global parser preferences + */ + public function setParserProperty($name, $value) + { + $this->parserPrefs[$name] = $value; + return; + } + + /** + * Get the global parser preferences + */ + public function getParserProperty($name) + { + return $this->parserPrefs[$name]; + } + + /** + * A helper function to load a class + * + * private + */ + private function _loadClass($name, $filename) + { + if ( !class_exists($name) ) + { + global $DIR_LIBS; + include($DIR_LIBS . $filename); + } + return; + } + + /** + * Manager::_loadPlugin() + * loading a certain plugin + * + * @param string $name plugin name + * @return void + */ + private function _loadPlugin($name) + { + global $DIR_PLUGINS, $MYSQL_HANDLER, $MYSQL_PREFIX; + + if ( class_exists($name) ) + { + return; + } + + $fileName = "{$DIR_PLUGINS}{$name}.php"; + + if ( !file_exists($fileName) ) + { + if ( !defined('_MANAGER_PLUGINFILE_NOTFOUND') ) + { + define('_MANAGER_PLUGINFILE_NOTFOUND', 'Plugin %s was not loaded (File not found)'); + } + ActionLog::add(WARNING, sprintf(_MANAGER_PLUGINFILE_NOTFOUND, $name)); + return 0; + } + + // load plugin + include($fileName); + + // check if class exists (avoid errors in eval'd code) + if ( !class_exists($name) ) + { + ActionLog::add(WARNING, sprintf(_MANAGER_PLUGINFILE_NOCLASS, $name)); + return 0; + } + + // add to plugin array + $this->plugins[$name] = new $name(); + + // get plugid + $this->plugins[$name]->setID($this->getPidFromName($name)); + + // unload plugin if a prefix is used and the plugin cannot handle this + if ( ($MYSQL_PREFIX != '') + && !$this->plugins[$name]->supportsFeature('SqlTablePrefix') ) + { + unset($this->plugins[$name]); + ActionLog::add(WARNING, sprintf(_MANAGER_PLUGINTABLEPREFIX_NOTSUPPORT, $name)); + return 0; + } + + // unload plugin if using non-mysql handler and plugin does not support it + if ( (!in_array('mysql',$MYSQL_HANDLER)) + && !$this->plugins[$name]->supportsFeature('SqlApi') ) + { + unset($this->plugins[$name]); + ActionLog::add(WARNING, sprintf(_MANAGER_PLUGINSQLAPI_NOTSUPPORT, $name)); + return 0; + } + + // call init method + $this->plugins[$name]->init(); + + return; + } + + /** + * Manager:getPlugin() + * Returns a PLUGIN object + * + * @param string $name name of plugin + * @return object plugin object + */ + public function &getPlugin($name) + { + // retrieve the name of the plugin in the right capitalisation + $name = $this->getUpperCaseName ($name); + + // get the plugin + $plugin =& $this->plugins[$name]; + + if ( !$plugin ) + { + // load class if needed + $this->_loadPlugin($name); + $plugin =& $this->plugins[$name]; + } + return $plugin; + } + + /** + * Manager::pluginLoaded() + * Checks if the given plugin IS loaded or not + * + * @param string $name name of plugin + * @return object plugin object + */ + public function &pluginLoaded($name) + { + $plugin =& $this->plugins[$name]; + return $plugin; + } + + /** + * Manager::pidLoaded() + * + * @param integer $pid id for plugin + * @return object plugin object + */ + public function &pidLoaded($pid) + { + $plugin=false; + reset($this->plugins); + while ( list($name) = each($this->plugins) ) + { + if ( $pid!=$this->plugins[$name]->getId() ) + { + continue; + } + $plugin= & $this->plugins[$name]; + break; + } + return $plugin; + } + + /** + * Manager::pluginInstalled() + * checks if the given plugin IS installed or not + * + * @param string $name name of plugin + * @return boolean exists or not + */ + public function pluginInstalled($name) + { + $this->_initCacheInfo('installedPlugins'); + return ($this->getPidFromName($name) != -1); + } + + /** + * Manager::pidInstalled() + * checks if the given plugin IS installed or not + * + * @param integer $pid id of plugin + * @return boolean exists or not + */ + public function pidInstalled($pid) + { + $this->_initCacheInfo('installedPlugins'); + return ($this->cachedInfo['installedPlugins'][$pid] != ''); + } + + /** + * Manager::getPidFromName() + * + * @param string $name name of plugin + * @return mixed id for plugin or -1 if not exists + */ + public function getPidFromName($name) + { + $this->_initCacheInfo('installedPlugins'); + foreach ( $this->cachedInfo['installedPlugins'] as $pid => $pfile ) + { + if (strtolower($pfile) == strtolower($name)) + { + return $pid; + } + } + return -1; + } + + /** + * Manager::getPluginNameFromPid() + * + * @param string $pid ID for plugin + * @return string name of plugin + */ + public function getPluginNameFromPid($pid) + { + if ( !array_key_exists($pid, $this->cachedInfo['installedPlugins']) ) + { + $query = 'SELECT pfile FROM %s WHERE pid=%d;'; + $query = sprintf($query, sql_table('plugin'), (integer) $pid); + return DB::getValue($query); + } + return $this->cachedInfo['installedPlugins'][$pid]; + } + + /** + * Manager::getUpperCaseName() + * Retrieve the name of a plugin in the right capitalisation + * + * @param string $name name of plugin + * @return string name according to UpperCamelCase + */ + public function getUpperCaseName ($name) + { + $this->_initCacheInfo('installedPlugins'); + foreach ( $this->cachedInfo['installedPlugins'] as $pid => $pfile ) + { + if ( strtolower($pfile) == strtolower($name) ) + { + return $pfile; + } + } + return -1; + } + + /** + * Manager::clearCachedInfo() + * + * @param string $what + * @return void + */ + public function clearCachedInfo($what) + { + unset($this->cachedInfo[$what]); + return; + } + + /** + * Manager::_initCacheInfo() + * Loads some info on the first call only + * + * @param string $what 'installedPlugins' + * @return void + */ + private function _initCacheInfo($what) + { + if ( array_key_exists($what, $this->cachedInfo) + && is_array($this->cachedInfo[$what]) ) + { + return; + } + + switch ($what) + { + // 'installedPlugins' = array ($pid => $name) + case 'installedPlugins': + $this->cachedInfo['installedPlugins'] = array(); + $res = DB::getResult('SELECT pid, pfile FROM ' . sql_table('plugin')); + foreach ( $res as $row ) + { + $this->cachedInfo['installedPlugins'][$row['pid']] = $row['pfile']; + } + break; + } + return; + } + + /** + * Manager::notify() + * A function to notify plugins that something has happened. Only the plugins + * that are subscribed to the event will get notified. + * Upon the first call, the list of subscriptions will be fetched from the + * database. The plugins itsself will only get loaded when they are first needed + * + * @param string $eventName Name of the event (method to be called on plugins) + * @param string $data Can contain any type of data, + * depending on the event type. Usually this is an itemid, blogid, ... + * but it can also be an array containing multiple values + * @return void + */ + public function notify($eventName, $data) + { + // load subscription list if needed + if ( !is_array($this->subscriptions) ) + { + $this->_loadSubscriptions(); + } + + // get listening objects + $listeners = false; + if ( array_key_exists($eventName, $this->subscriptions) + && !empty($this->subscriptions[$eventName]) ) + { + $listeners = $this->subscriptions[$eventName]; + } + + // notify all of them + if ( is_array($listeners) ) + { + foreach( $listeners as $listener ) + { + // load class if needed + $this->_loadPlugin($listener); + + // do notify (if method exists) + if ( array_key_exists($listener, $this->plugins) + && !empty($this->plugins[$listener]) + && method_exists($this->plugins[$listener], 'event_' . $eventName) ) + { + call_user_func(array(&$this->plugins[$listener],'event_' . $eventName), $data); + } + } + } + return; + } + + /** + * Manager::_loadSubscriptions() + * Loads plugin subscriptions + * + * @param void + * @return void + */ + private function _loadSubscriptions() + { + // initialize as array + $this->subscriptions = array(); + + $query = "SELECT p.pfile as pfile, e.event as event" + . " FROM %s as e, %s as p" + . " WHERE e.pid=p.pid ORDER BY p.porder ASC"; + $query = sprintf($query, sql_table('plugin_event'), sql_table('plugin')); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $pluginName = $row['pfile']; + $eventName = $row['event']; + $this->subscriptions[$eventName][] = $pluginName; + } + return; + } + + /** + * Manager::getNumberOfSubscribers() + * + * @param string $event name of events + * @return integer number of event subscriber + */ + public function getNumberOfSubscribers($event) + { + $query = 'SELECT COUNT(*) as count FROM %s WHERE event=%s;'; + $query = sprintf($query, sql_table('plugin_event'), DB::quoteValue($event)); + return (integer) DB::getValue($query); + } + + /** + * Manager::addTicketToUrl() + * GET requests: Adds ticket to URL (URL should NOT be html-encoded!, ticket is added at the end) + * + * @param string url string for URI + * @return void + */ + public function addTicketToUrl($url) + { + $ticketCode = 'ticket=' . $this->_generateTicket(); + if ( i18n::strpos($url, '?') === FALSE ) + { + $ticketCode = "{$url}?{$ticketCode}"; + } + else + { + $ticketCode = "{$url}&{$ticketCode}"; + } + return $ticketCode; + } + + /** + * Manager::addTicketHidden() + * POST requests: Adds ticket as hidden formvar + * + * @param void + * @return void + */ + public function addTicketHidden() + { + $ticket = $this->_generateTicket(); + echo ''; + return; + } + + /** + * Manager::getNewTicket() + * Get a new ticket + * (xmlHTTPRequest AutoSaveDraft uses this to refresh the ticket) + * + * @param void + * @return string string of ticket + */ + public function getNewTicket() + { + $this->currentRequestTicket = ''; + return $this->_generateTicket(); + } + + /** + * Manager::checkTicket() + * Checks the ticket that was passed along with the current request + * + * @param void + * @return boolean correct or not + */ + public function checkTicket() + { + global $member; + + // get ticket from request + $ticket = requestVar('ticket'); + + // no ticket -> don't allow + if ( $ticket == '' ) + { + return FALSE; + } + + // remove expired tickets first + $this->_cleanUpExpiredTickets(); + + // get member id + if (!$member->isLoggedIn()) + { + $memberId = -1; + } + else + { + $memberId = $member->getID(); + } + + // check if ticket is a valid one + $query = sprintf('SELECT COUNT(*) as result FROM %s WHERE member=%d and ticket=%s', + sql_table('tickets'), + intval($memberId), + DB::quoteValue($ticket) + ); + + /* + * NOTE: + * [in the original implementation, the checked ticket was deleted. This would lead to invalid + * tickets when using the browsers back button and clicking another link/form + * leaving the keys in the database is not a real problem, since they're member-specific and + * only valid for a period of one hour] + */ + if ( DB::getValue($query) != 1 ) + { + return FALSE; + } + + return TRUE; + } + + /** + * Manager::_cleanUpExpiredTickets() + * Removes the expired tickets + * + * @param void + * @return void + */ + private function _cleanUpExpiredTickets() + { + // remove tickets older than 1 hour + $oldTime = time() - 60 * 60; + $query = 'DELETE FROM %s WHERE ctime < %s'; + $query = sprintf($query, sql_table('tickets'), DB::formatDateTime($oldTime)); + DB::execute($query); + return; + } + + /** + * Manager::_generateTicket() + * Generates/returns a ticket (one ticket per page request) + * + * @param void + * @return void + */ + private function _generateTicket() + { + if ( $this->currentRequestTicket == '' ) + { + // generate new ticket (only one ticket will be generated per page request) + // and store in database + global $member; + // get member id + if ( !$member->isLoggedIn() ) + { + $memberId = -1; + } + else + { + $memberId = $member->getID(); + } + + $ok = false; + while ( !$ok ) + { + // generate a random token + srand((double)microtime()*1000000); + $ticket = md5(uniqid(rand(), true)); + + // add in database as non-active + $query = 'INSERT INTO %s (ticket, member, ctime) VALUES (%s, %d, %s)'; + $query = sprintf($query, sql_table('tickets'), DB::quoteValue($ticket), (integer) $memberId, DB::formatDateTime()); + + if ( DB::execute($query) !== FALSE ) + { + $ok = true; + } + } + $this->currentRequestTicket = $ticket; + } + return $this->currentRequestTicket; + } +} + ++======= + $name) + */ + private $cachedInfo; + + /** + * The plugin subscriptionlist + * + * The subcription array has the following structure + * $subscriptions[$EventName] = array containing names of plugin classes to be + * notified when that event happens + * + * NOTE: this is referred by Comments::addComment() for spamcheck API + * TODO: we should add new methods to get this + */ + public $subscriptions; + + /** + * Ticket functions. These are uses by the admin area to make it impossible to simulate certain GET/POST + * requests. tickets are user specific + */ + private $currentRequestTicket = ''; + + /** + * Returns the only instance of this class. Creates the instance if it + * does not yet exists. Users should use this function as + * $manager =& Manager::instance(); to get a reference to the object + * instead of a copy + */ + static public function &instance() + { + static $instance = array(); + if ( empty($instance) ) + { + $instance[0] = new Manager(); + } + return $instance[0]; + } + + /** + * The constructor of this class initializes the object caches + */ + public function __construct() + { + $this->items = array(); + $this->blogs = array(); + $this->plugins = array(); + $this->karma = array(); + $this->templates = array(); + $this->skins = array(); + $this->parserPrefs = array(); + $this->cachedInfo = array(); + $this->members = array(); + return; + } + + /** + * Returns the requested item object. If it is not in the cache, it will + * first be loaded and then placed in the cache. + * Intended use: $item =& $manager->getItem(1234, 0, 0) + */ + public function &getItem($itemid, $allowdraft, $allowfuture) + { + /* confirm to cached */ + if ( !array_key_exists($itemid, $this->items) ) + { + $this->loadClass('ITEM'); + $item = Item::getitem($itemid, $allowdraft, $allowfuture); + $this->items[$itemid] = $item; + } + + $item =& $this->items[$itemid]; + if ( !$allowdraft && ($item['draft']) ) + { + return 0; + } + + $blog =& $this->getBlog($item['blogid']); + if ( !$allowfuture && ($item['timestamp'] > $blog->getCorrectTime()) ) + { + return 0; + } + + return $item; + } + + /** + * Loads a class if it has not yet been loaded + */ + public function loadClass($name) + { + $this->_loadClass($name, $name . '.php'); + return; + } + + /** + * Checks if an item exists + */ + public function existsItem($id,$future,$draft) + { + $this->_loadClass('ITEM','ITEM.php'); + return Item::exists($id,$future,$draft); + } + + /** + * Checks if a category exists + */ + public function existsCategory($id) + { + return (DB::getValue('SELECT COUNT(*) as result FROM '.sql_table('category').' WHERE catid='.intval($id)) > 0); + } + + /** + * Returns the blog object for a given blogid + */ + public function &getBlog($blogid) + { + if ( !array_key_exists($blogid, $this->blogs) ) + { + $this->_loadClass('BLOG','BLOG.php'); + $this->blogs[$blogid] = new Blog($blogid); + } + return $this->blogs[$blogid]; + } + + /** + * Checks if a blog exists + */ + public function existsBlog($name) + { + $this->_loadClass('BLOG','BLOG.php'); + return Blog::exists($name); + } + + /** + * Checks if a blog id exists + */ + public function existsBlogID($id) + { + $this->_loadClass('BLOG','BLOG.php'); + return Blog::existsID($id); + } + + /** + * Returns a previously read template + */ + public function &getTemplate($templateName) + { + if ( !array_key_exists($templateName, $this->templates) ) + { + $this->_loadClass('Template','TEMPLATE.php'); + $tmplate_tmp = Template::read($templateName); + $this->templates[$templateName] =& $tmplate_tmp; + } + return $this->templates[$templateName]; + } + + /** + * Returns a KARMA object (karma votes) + */ + public function &getKarma($itemid) + { + if ( !array_key_exists($itemid, $this->karma) ) + { + $this->_loadClass('Karma','KARMA.php'); + $this->karma[$itemid] = new Karma($itemid); + } + return $this->karma[$itemid]; + } + + /** + * Returns a MEMBER object + */ + public function &getMember($memberid) + { + if ( !array_key_exists($memberid, $this->members) ) + { + $this->_loadClass('Member','MEMBER.php'); + $this->members[$memberid] =& Member::createFromID($memberid);; + } + return $this->members[$memberid]; + } + + /** + * Manager::getSkin() + * + * @param integer $skinid ID for skin + * @param string $action_class action class for handling skin variables + * @param string $event_identifier identifier for event name + * @return object instance of Skin class + */ + public function &getSkin($skinid, $action_class='Actions', $event_identifier='Skin') + { + if ( !array_key_exists($skinid, $this->skins) ) + { + $this->_loadClass('Skin', 'SKIN.php'); + $this->skins[$skinid] = new Skin($skinid, $action_class, $event_identifier); + } + + return $this->skins[$skinid]; + } + + /** + * Set the global parser preferences + */ + public function setParserProperty($name, $value) + { + $this->parserPrefs[$name] = $value; + return; + } + + /** + * Get the global parser preferences + */ + public function getParserProperty($name) + { + return $this->parserPrefs[$name]; + } + + /** + * A helper function to load a class + * + * private + */ + private function _loadClass($name, $filename) + { + global $DIR_LIBS; + + if ( !class_exists($name) ) + { + include($DIR_LIBS . $filename); + } + return; + } + + /** + * Manager::_loadPlugin() + * loading a certain plugin + * + * @param string $name plugin name + * @return void + */ + private function _loadPlugin($name) + { + global $DIR_PLUGINS, $MYSQL_HANDLER, $MYSQL_PREFIX; + + if ( class_exists($name) ) + { + return; + } + + $fileName = "{$DIR_PLUGINS}{$name}.php"; + + if ( !file_exists($fileName) ) + { + if ( !defined('_MANAGER_PLUGINFILE_NOTFOUND') ) + { + define('_MANAGER_PLUGINFILE_NOTFOUND', 'Plugin %s was not loaded (File not found)'); + } + ActionLog::add(WARNING, sprintf(_MANAGER_PLUGINFILE_NOTFOUND, $name)); + return 0; + } + + // load plugin + include($fileName); + + // check if class exists (avoid errors in eval'd code) + if ( !class_exists($name) ) + { + ActionLog::add(WARNING, sprintf(_MANAGER_PLUGINFILE_NOCLASS, $name)); + return 0; + } + + // add to plugin array + $this->plugins[$name] = new $name(); + + // get plugid + $this->plugins[$name]->setID($this->getPidFromName($name)); + + // unload plugin if a prefix is used and the plugin cannot handle this + if ( ($MYSQL_PREFIX != '') + && !$this->plugins[$name]->supportsFeature('SqlTablePrefix') ) + { + unset($this->plugins[$name]); + ActionLog::add(WARNING, sprintf(_MANAGER_PLUGINTABLEPREFIX_NOTSUPPORT, $name)); + return 0; + } + + // unload plugin if using non-mysql handler and plugin does not support it + if ( (!in_array('mysql',$MYSQL_HANDLER)) + && !$this->plugins[$name]->supportsFeature('SqlApi') ) + { + unset($this->plugins[$name]); + ActionLog::add(WARNING, sprintf(_MANAGER_PLUGINSQLAPI_NOTSUPPORT, $name)); + return 0; + } + + // call init method + $this->plugins[$name]->init(); + + return; + } + + /** + * Manager:getPlugin() + * Returns a PLUGIN object + * + * @param string $name name of plugin + * @return object plugin object + */ + public function &getPlugin($name) + { + // retrieve the name of the plugin in the right capitalisation + $name = $this->getUpperCaseName ($name); + + // get the plugin + $plugin =& $this->plugins[$name]; + + if ( !$plugin ) + { + // load class if needed + $this->_loadPlugin($name); + $plugin =& $this->plugins[$name]; + } + return $plugin; + } + + /** + * Manager::pluginLoaded() + * Checks if the given plugin IS loaded or not + * + * @param string $name name of plugin + * @return object plugin object + */ + public function &pluginLoaded($name) + { + $plugin =& $this->plugins[$name]; + return $plugin; + } + + /** + * Manager::pidLoaded() + * + * @param integer $pid id for plugin + * @return object plugin object + */ + public function &pidLoaded($pid) + { + $plugin=false; + reset($this->plugins); + while ( list($name) = each($this->plugins) ) + { + if ( $pid!=$this->plugins[$name]->getId() ) + { + continue; + } + $plugin= & $this->plugins[$name]; + break; + } + return $plugin; + } + + /** + * Manager::pluginInstalled() + * checks if the given plugin IS installed or not + * + * @param string $name name of plugin + * @return boolean exists or not + */ + public function pluginInstalled($name) + { + $this->_initCacheInfo('installedPlugins'); + return ($this->getPidFromName($name) != -1); + } + + /** + * Manager::pidInstalled() + * checks if the given plugin IS installed or not + * + * @param integer $pid id of plugin + * @return boolean exists or not + */ + public function pidInstalled($pid) + { + $this->_initCacheInfo('installedPlugins'); + return ($this->cachedInfo['installedPlugins'][$pid] != ''); + } + + /** + * Manager::getPidFromName() + * + * @param string $name name of plugin + * @return mixed id for plugin or -1 if not exists + */ + public function getPidFromName($name) + { + $this->_initCacheInfo('installedPlugins'); + foreach ( $this->cachedInfo['installedPlugins'] as $pid => $pfile ) + { + if (strtolower($pfile) == strtolower($name)) + { + return $pid; + } + } + return -1; + } + + /** + * Manager::getPluginNameFromPid() + * + * @param string $pid ID for plugin + * @return string name of plugin + */ + public function getPluginNameFromPid($pid) + { + if ( !array_key_exists($pid, $this->cachedInfo['installedPlugins']) ) + { + $query = 'SELECT pfile FROM %s WHERE pid=%d;'; + $query = sprintf($query, sql_table('plugin'), (integer) $pid); + return DB::getValue($query); + } + return $this->cachedInfo['installedPlugins'][$pid]; + } + + /** + * Manager::getUpperCaseName() + * Retrieve the name of a plugin in the right capitalisation + * + * @param string $name name of plugin + * @return string name according to UpperCamelCase + */ + public function getUpperCaseName ($name) + { + $this->_initCacheInfo('installedPlugins'); + foreach ( $this->cachedInfo['installedPlugins'] as $pid => $pfile ) + { + if ( strtolower($pfile) == strtolower($name) ) + { + return $pfile; + } + } + return -1; + } + + /** + * Manager::clearCachedInfo() + * + * @param string $what + * @return void + */ + public function clearCachedInfo($what) + { + unset($this->cachedInfo[$what]); + return; + } + + /** + * Manager::_initCacheInfo() + * Loads some info on the first call only + * + * @param string $what 'installedPlugins' + * @return void + */ + private function _initCacheInfo($what) + { + if ( array_key_exists($what, $this->cachedInfo) + && is_array($this->cachedInfo[$what]) ) + { + return; + } + + switch ($what) + { + // 'installedPlugins' = array ($pid => $name) + case 'installedPlugins': + $this->cachedInfo['installedPlugins'] = array(); + $res = DB::getResult('SELECT pid, pfile FROM ' . sql_table('plugin')); + foreach ( $res as $row ) + { + $this->cachedInfo['installedPlugins'][$row['pid']] = $row['pfile']; + } + break; + } + return; + } + + /** + * Manager::notify() + * A function to notify plugins that something has happened. Only the plugins + * that are subscribed to the event will get notified. + * Upon the first call, the list of subscriptions will be fetched from the + * database. The plugins itsself will only get loaded when they are first needed + * + * @param string $eventName Name of the event (method to be called on plugins) + * @param string $data Can contain any type of data, + * depending on the event type. Usually this is an itemid, blogid, ... + * but it can also be an array containing multiple values + * @return void + */ + public function notify($eventName, &$data) + { + // load subscription list if needed + if ( !is_array($this->subscriptions) ) + { + $this->_loadSubscriptions(); + } + + // get listening objects + $listeners = false; + if ( array_key_exists($eventName, $this->subscriptions) + && !empty($this->subscriptions[$eventName]) ) + { + $listeners = $this->subscriptions[$eventName]; + } + + // notify all of them + if ( is_array($listeners) ) + { + foreach( $listeners as $listener ) + { + // load class if needed + $this->_loadPlugin($listener); + + // do notify (if method exists) + if ( array_key_exists($listener, $this->plugins) + && !empty($this->plugins[$listener]) + && method_exists($this->plugins[$listener], 'event_' . $eventName) ) + { + call_user_func(array($this->plugins[$listener], 'event_' . $eventName), $data); + } + } + } + return; + } + + /** + * Manager::_loadSubscriptions() + * Loads plugin subscriptions + * + * @param void + * @return void + */ + private function _loadSubscriptions() + { + // initialize as array + $this->subscriptions = array(); + + $query = "SELECT p.pfile as pfile, e.event as event" + . " FROM %s as e, %s as p" + . " WHERE e.pid=p.pid ORDER BY p.porder ASC"; + $query = sprintf($query, sql_table('plugin_event'), sql_table('plugin')); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $pluginName = $row['pfile']; + $eventName = $row['event']; + $this->subscriptions[$eventName][] = $pluginName; + } + return; + } + + /** + * Manager::getNumberOfSubscribers() + * + * @param string $event name of events + * @return integer number of event subscriber + */ + public function getNumberOfSubscribers($event) + { + $query = 'SELECT COUNT(*) as count FROM %s WHERE event=%s;'; + $query = sprintf($query, sql_table('plugin_event'), DB::quoteValue($event)); + return (integer) DB::getValue($query); + } + + /** + * Manager::addTicketToUrl() + * GET requests: Adds ticket to URL (URL should NOT be html-encoded!, ticket is added at the end) + * + * @param string url string for URI + * @return void + */ + public function addTicketToUrl($url) + { + $ticketCode = 'ticket=' . $this->_generateTicket(); + if ( i18n::strpos($url, '?') === FALSE ) + { + $ticketCode = "{$url}?{$ticketCode}"; + } + else + { + $ticketCode = "{$url}&{$ticketCode}"; + } + return $ticketCode; + } + + /** + * Manager::addTicketHidden() + * POST requests: Adds ticket as hidden formvar + * + * @param void + * @return void + */ + public function addTicketHidden() + { + $ticket = $this->_generateTicket(); + echo ''; + return; + } + + /** + * Manager::getNewTicket() + * Get a new ticket + * (xmlHTTPRequest AutoSaveDraft uses this to refresh the ticket) + * + * @param void + * @return string string of ticket + */ + public function getNewTicket() + { + $this->currentRequestTicket = ''; + return $this->_generateTicket(); + } + + /** + * Manager::checkTicket() + * Checks the ticket that was passed along with the current request + * + * @param void + * @return boolean correct or not + */ + public function checkTicket() + { + global $member; + + // get ticket from request + $ticket = requestVar('ticket'); + + // no ticket -> don't allow + if ( $ticket == '' ) + { + return FALSE; + } + + // remove expired tickets first + $this->_cleanUpExpiredTickets(); + + // get member id + if (!$member->isLoggedIn()) + { + $memberId = -1; + } + else + { + $memberId = $member->getID(); + } + + // check if ticket is a valid one + $query = sprintf('SELECT COUNT(*) as result FROM %s WHERE member=%d and ticket=%s', + sql_table('tickets'), + intval($memberId), + DB::quoteValue($ticket) + ); + + /* + * NOTE: + * [in the original implementation, the checked ticket was deleted. This would lead to invalid + * tickets when using the browsers back button and clicking another link/form + * leaving the keys in the database is not a real problem, since they're member-specific and + * only valid for a period of one hour] + */ + if ( DB::getValue($query) != 1 ) + { + return FALSE; + } + + return TRUE; + } + + /** + * Manager::_cleanUpExpiredTickets() + * Removes the expired tickets + * + * @param void + * @return void + */ + private function _cleanUpExpiredTickets() + { + // remove tickets older than 1 hour + $oldTime = time() - 60 * 60; + $query = 'DELETE FROM %s WHERE ctime < %s'; + $query = sprintf($query, sql_table('tickets'), DB::formatDateTime($oldTime)); + DB::execute($query); + return; + } + + /** + * Manager::_generateTicket() + * Generates/returns a ticket (one ticket per page request) + * + * @param void + * @return void + */ + private function _generateTicket() + { + if ( $this->currentRequestTicket == '' ) + { + // generate new ticket (only one ticket will be generated per page request) + // and store in database + global $member; + // get member id + if ( !$member->isLoggedIn() ) + { + $memberId = -1; + } + else + { + $memberId = $member->getID(); + } + + $ok = false; + while ( !$ok ) + { + // generate a random token + srand((double)microtime()*1000000); + $ticket = md5(uniqid(rand(), true)); + + // add in database as non-active + $query = 'INSERT INTO %s (ticket, member, ctime) VALUES (%s, %d, %s)'; + $query = sprintf($query, sql_table('tickets'), DB::quoteValue($ticket), (integer) $memberId, DB::formatDateTime()); + + if ( DB::execute($query) !== FALSE ) + { + $ok = true; + } + } + $this->currentRequestTicket = $ticket; + } + return $this->currentRequestTicket; + } + } + ++>>>>>>> skinnable-master diff --combined nucleus/libs/MEDIA.php index 1c6ab00,422fd16..66f8c66 --- a/nucleus/libs/MEDIA.php +++ b/nucleus/libs/MEDIA.php @@@ -1,789 -1,791 +1,1583 @@@ ++<<<<<<< HEAD + '.jpeg', + 'image/png' => '.png', + 'image/gif' => '.gif', + ); + + /** + * Media::getCollectionList() + * Gets the list of collections available to the currently logged + * in member + * + * @param boolean $exceptReadOnly + * @return array dirname => display name + */ + static public function getCollectionList($exceptReadOnly = FALSE) + { + global $member, $DIR_MEDIA; + + $collections = array(); + + // add private directory for member + $collections[$member->getID()] = PRIVATE_COLLECTION; + + // add global collections + if ( !is_dir($DIR_MEDIA) ) + { + return $collections; + } + + $dirhandle = opendir($DIR_MEDIA); + while ( $dirname = readdir($dirhandle) ) + { + // only add non-numeric (numeric=private) dirs + if ( @is_dir($DIR_MEDIA . $dirname) && + ($dirname != '.') && + ($dirname != '..') && + ($dirname != self::$thumbdir) && + (!is_numeric($dirname)) ) + { + if ( @is_writable($DIR_MEDIA . $dirname) ) + { + $collections[$dirname] = $dirname; + } + else if ( $exceptReadOnly == FALSE ) + { + $collections[$dirname] = $dirname . ' ' . READ_ONLY_MEDIA_FOLDER; + } + } + } + closedir($dirhandle); + + return $collections; + } + + /** + * Media::getMediaListByCollection() + * Returns an array of MediaObject objects for a certain collection + * + * @param string $collection name of the collection + * @param string $filter filter on filename (defaults to none) + * @return void + */ + static public function getMediaListByCollection($collection, $filter = '') + { + global $CONF, $DIR_MEDIA; + + $filelist = array(); + + // 1. go through all objects and add them to the filelist + $mediadir = $DIR_MEDIA . $collection . '/'; + + // return if dir does not exist + if ( !is_dir($mediadir) ) + { + return $filelist; + } + + $dirhandle = opendir($mediadir); + while ( $filename = readdir($dirhandle) ) + { + // only add files that match the filter + if ( !is_dir($mediadir . $filename) && self::checkFilter($filename, $filter) ) + { + array_push($filelist, new MediaObject($collection, $filename, $DIR_MEDIA)); + } + } + closedir($dirhandle); + + /* sort array */ + if ( !$CONF['MediaPrefix'] ) + { + usort($filelist, array(__CLASS__, 'sort_media_by_timestamp')); + } + else + { + usort($filelist, array(__CLASS__, 'sort_media_by_filename')); + } + + return $filelist; + } + + /** + * Media::checkFilter() + * + * @param string $strText + * @param string $strFilter + * @return boolean + */ + static public function checkFilter($strText, $strFilter) + { + if ( $strFilter == '' ) + { + return 1; + } + else + { + return is_integer(i18n::strpos(strtolower($strText), strtolower($strFilter))); + } + } + + /** + * Media::isValidCollection() + * checks if a collection exists with the given name, and if it's + * allowed for the currently logged in member to upload files to it + * + * @param string $collectionName + * @param string $exceptReadOnly + * @return boolean + */ + static public function isValidCollection($collectionName, $exceptReadOnly = FALSE) + { + global $member, $DIR_MEDIA; + + // allow creating new private directory + if ( $collectionName === (string)$member->getID() ) + { + return TRUE; + } + + $collections = self::getCollectionList($exceptReadOnly); + $dirname = $collections[$collectionName]; + + if ( $dirname == NULL || $dirname === PRIVATE_COLLECTION ) + { + return FALSE; + } + + // other collections should exist and be writable + $collectionDir = $DIR_MEDIA . $collectionName; + if ( $exceptReadOnly ) + { + return ( @is_dir($collectionDir) && @is_writable($collectionDir) ); + } + + // other collections should exist + return @is_dir($collectionDir); + } + + /** + * Media::addMediaObject() + * Adds an uploaded file to the media archive + * + * @param string $collection collection + * @param array $uploadfile the postFileInfo(..) array + * @param string $filename the filename that should be used to save the file as + * (date prefix should be already added here) + * @return string blank if success, message if failed + */ + static public function addMediaObject($collection, $uploadfile, $filename) + { + global $DIR_MEDIA, $manager; + + // clean filename of characters that may cause trouble in a filename using cleanFileName() function from globalfunctions.php + $filename = cleanFileName($filename); + + // should already have tested for allowable types before calling this method. This will only catch files with no extension at all + if ( $filename === FALSE ) + { + return _ERROR_BADFILETYPE; + } + + // trigger PreMediaUpload event + $manager->notify('PreMediaUpload',array('collection' => &$collection, 'uploadfile' => $uploadfile, 'filename' => &$filename)); + + // don't allow uploads to unknown or forbidden collections + $exceptReadOnly = TRUE; + if ( !self::isValidCollection($collection,$exceptReadOnly) ) + { + return _ERROR_DISALLOWED; + } + + // check dir permissions (try to create dir if it does not exist) + $mediadir = $DIR_MEDIA . $collection; + + // try to create new private media directories if needed + if ( !@is_dir($mediadir) && is_numeric($collection) ) + { + $oldumask = umask(0000); + if ( !@mkdir($mediadir, 0777) ) + { + return _ERROR_BADPERMISSIONS; + } + umask($oldumask); + } + + // if dir still not exists, the action is disallowed + if ( !@is_dir($mediadir) ) + { + return _ERROR_DISALLOWED; + } + + if ( !is_writeable($mediadir) ) + { + return _ERROR_BADPERMISSIONS; + } + + // add trailing slash (don't add it earlier since it causes mkdir to fail on some systems) + $mediadir .= '/'; + + if ( file_exists($mediadir . $filename) ) + { + return _ERROR_UPLOADDUPLICATE; + } + + // move file to directory + if ( is_uploaded_file($uploadfile) ) + { + if ( !@move_uploaded_file($uploadfile, $mediadir . $filename) ) + { + return _ERROR_UPLOADMOVEP; + } + } + else + { + if ( !copy($uploadfile, $mediadir . $filename) ) + { + return _ERROR_UPLOADCOPY ; + } + } + + // chmod uploaded file + $oldumask = umask(0000); + @chmod($mediadir . $filename, 0644); + umask($oldumask); + + $manager->notify('PostMediaUpload',array('collection' => $collection, 'mediadir' => $mediadir, 'filename' => $filename)); + + return ''; + } + + /** + * Media::addMediaObjectRaw() + * Adds an uploaded file to the media dir. + * + * NOTE: does not check if $collection is valid. + * + * @param string $collection collection to use + * @param string $filename the filename that should be used to save the file + * as (date prefix should be already added here) + * @param &$data File data (binary) + * @return string blank if success, message if failed + */ + static public function addMediaObjectRaw($collection, $filename, &$data) + { + global $DIR_MEDIA; + + // check dir permissions (try to create dir if it does not exist) + $mediadir = $DIR_MEDIA . $collection; + + // try to create new private media directories if needed + if ( !@is_dir($mediadir) && is_numeric($collection) ) + { + $oldumask = umask(0000); + if ( !@mkdir($mediadir, 0777) ) + { + return _ERROR_BADPERMISSIONS; + } + umask($oldumask); + } + + // if dir still not exists, the action is disallowed + if ( !@is_dir($mediadir) ) + { + return _ERROR_DISALLOWED; + } + + if ( !is_writeable($mediadir) ) + { + return _ERROR_BADPERMISSIONS; + } + + // add trailing slash (don't add it earlier since it causes mkdir to fail on some systems) + $mediadir .= '/'; + + if ( file_exists($mediadir . $filename) ) + { + return _ERROR_UPLOADDUPLICATE; + } + + // create file + $fh = @fopen($mediadir . $filename, 'wb'); + if ( !$fh ) + { + return _ERROR_UPLOADFAILED; + } + $ok = @fwrite($fh, $data); + @fclose($fh); + if ( !$ok ) + { + return _ERROR_UPLOADFAILED; + } + + // chmod uploaded file + $oldumask = umask(0000); + @chmod($mediadir . $filename, 0644); + umask($oldumask); + + return ''; + } + + /** + * Media::responseResampledImage() + * send resampled image via HTTP + * + * @param object $medium MediaObject Object + * @exit + */ + static public function responseResampledImage($medium, $maxwidth=0, $maxheight=0) + { + if ( get_class($medium) !== 'MediaObject' ) + { + header("HTTP/1.1 500 Internal Server Error"); + exit('Nucleus CMS: Fail to generate resampled image'); + return; + } + + $resampledimage = $medium->getResampledBinary($maxwidth, $maxheight); + if ( $resampledimage === FALSE ) + { + unset($resampledimage); + header("HTTP/1.1 503 Service Unavailable"); + exit('Nucleus CMS: Fail to generate resampled image'); + return; + } + + header("Content-type: {$medium->mime}"); + echo $resampledimage; + + unset($resampledimage); + + exit; + } + + /** + * Media::storeResampledImage() + * Store resampled image binary to filesystem as file + * + * @param object $medium MediaObject Object + * @param integer $maxwidth maximum width + * @param integer $maxheight maximum height + * @param string $path directory path for destination + * @param string $name file name for destination + * @return boolean + */ + static public function storeResampledImage($medium, $maxwidth=0, $maxheight=0, $path='', $name='') + { + global $DIR_MEDIA; + + if ( get_class($medium) !== 'MediaObject' ) + { + return FALSE; + } + + if ( $path !== '' ) + { + $path = realpath($path); + if ( !file_exists($path) + || strpos($path, $DIR_MEDIA) !== 0 ) + { + return FALSE; + } + } + else + { + $path = '$DIR_MEDIA/' . self::$thumbdir; + } + + if ( $name === '' ) + { + $name = $medium->getHashedname(); + } + + $resampledimage = $medium->getResampledBinary($maxwidth, $maxheight); + if ( !$resampledimage ) + { + unset($resampledimage); + return FALSE; + } + + $handle = @fopen("{$path}/{$name}", 'w'); + if ( !$handle ) + { + unset ($resampledimage); + return FALSE; + } + + if ( !@fwrite($handle, $resampledimage) ) + { + unset($resampledimage); + @unlink("{$path}/{$name}"); + return FALSE; + } + + unset($resampledimage); + fclose($handle); + + if ( !@chmod("{$path}/{$name}", 0774) ) + { + @unlink("{$path}/{$name}"); + return FALSE; + } + + return TRUE; + } + + /** + * Media::sort_media_by_timestamp() + * User-defined sort method to sort an array of MediaObjects + * + * @param object $a + * @param object $b + * @return boolean + */ + static private function sort_media_by_timestamp($a, $b) + { + if ($a->timestamp == $b->timestamp) return 0; + return ($a->timestamp > $b->timestamp) ? -1 : 1; + } + + /** + * Media::sort_media_by_filename() + * User-defined sort method to sort an array of MediaObjects + * + * @param object $a + * @param object $b + * @return boolean + */ + static private function sort_media_by_filename($a, $b) + { + if ($a->filename == $b->filename) return 0; + return ($a->filename > $b->filename) ? -1 : 1; + } +} + +class MediaObject +{ + public $mime = ''; + + public $root = ''; + public $path = ''; + public $private; + public $collection; + public $filename = ''; + + public $prefix = ''; + public $name = ''; + public $suffix = ''; + + public $timestamp = 0; + public $size = 0; + + public $width = 0; + public $height = 0; + public $resampledwidth = 0; + public $resampledheight = 0; + + /** + * MediaObject::__construct() + * + * @param string $collection + * @param string $filename + * @param string $root fullpath to media directory + */ + public function __construct($collection, $filename, $root=0) + { + global $CONF, $DIR_MEDIA; + + /* for backward compatibility */ + if ( is_numeric($root) ) + { + $root = $DIR_MEDIA; + } + + $root = preg_replace('#/*$#', '', $root); + + /* get and validate fullpath for the medium */ + if ( !file_exists($root) + || FALSE === ($fullpath = realpath("{$root}/{$collection}/{$filename}")) + || strpos($fullpath, $root) !== 0 + || !file_exists($fullpath) ) + { + return FALSE; + } + + /* store fundamentals */ + $this->root = $root; + $this->private = (integer) $collection; + $this->collection = $collection; + $this->filename = basename($fullpath); + $this->timestamp = filemtime($fullpath); + + /* store relative directory path from root directory for media */ + $this->path = preg_replace(array("#{$this->root}/#", "#/{$this->filename}#"), '', $fullpath); + if ( $this->path === $this->name ) + { + $this->path = ''; + } + + return; + } + + /** + * MediaObject::refine() + * refine data + * + * @param void + * @return void + */ + public function refine() + { + global $CONF; + + /* store size (byte order) */ + $this->size = filesize("{$this->root}/{$this->path}/{$this->filename}"); + + /* get width and height if this is image binary */ + if ( FALSE === ($info = @getimagesize ("{$this->root}/{$this->path}/{$this->filename}")) ) + { + $this->mime = 'application/octet-stream'; + $this->width = 0; + $this->height = 0; + } + else + { + $this->mime = $info['mime']; + $this->width = $info[0]; + $this->height = $info[1]; + } + + /* utilise Fileinfo subsystem if available */ + if ( defined('FILEINFO_MIME_TYPE') && function_exists ('finfo_open') + && (FALSE !== ($info = finfo_open(FILEINFO_MIME_TYPE))) ) + { + $this->mime = finfo_file($info, "{$this->root}/{$this->path}/{$this->filename}"); + } + + /* store data with parsed filename */ + if ( preg_match('#^(.*)\.([a-zA-Z0-9]{2,})$#', $this->filename, $info) === 1 ) + { + $this->name = $info[1]; + $this->suffix = $info[2]; + + if ( $CONF['MediaPrefix'] && preg_match('#^([0-9]{8})\-(.*)$#', $this->name, $info) == 1 ) + { + $this->prefix = preg_replace('#^([0-9]{4})([0-9]{2})([0-9]{2})$#', '$1/$2/$3', $info[1]); + $this->name = $info[2]; + } + } + + return; + } + + /** + * MediaObject::setResampledSize() + * Set resampled size + * + * @param integer $maxwidth + * @param integer $maxheight + * @return boolean + */ + public function setResampledSize($maxwidth=0, $maxheight=0) + { + if ( ($maxwidth == 0) && ($maxheight == 0) ) + { + return FALSE; + } + else if ( $this->width == 0 || $this->height == 0 ) + { + return FALSE; + } + else if ($this->width < $maxwidth && $this->height < $maxheight ) + { + $this->resampledwidth = $this->width; + $this->resampledheight = $this->height; + } + else if ( $maxheight == 0 || $this->width > $this->height ) + { + $this->resampledheight = intval ($this->height * $maxwidth / $this->width); + $this->resampledwidth = $maxwidth; + } + else if ( $maxwidth == 0 || $this->width <= $this->height ) + { + $this->resampledwidth = intval ($this->width * $maxheight / $this->height); + $this->resampledheight = $maxheight; + } + return TRUE; + } + + /** + * MediaObject::getResampledBinary() + * Return resampled image binary + * + * @param void + * @return mixed binary if success, FALSE if failed + */ + public function getResampledBinary($maxwidth=0, $maxheight=0) + { + static $gdinfo = array(); + static $original; + static $resampledimage; + + if ( !$this->setResampledSize($maxwidth, $maxheight) ) + { + return FALSE; + } + + if ( $gdinfo = array() ) + { + $gdinfo = gd_info(); + } + + if ( $this->path !== '' ) + { + $fullpath = "{$this->root}/{$this->path}/{$this->name}"; + } + else + { + $fullpath = "{$this->root}/{$this->name}"; + } + if ( !file_exists($fullpath) ) + { + return FALSE; + } + + if ( !array_key_exists($this->mime, Media::$image_mime) + || $this->width == 0 + || $this->height == 0 + || $this->resampledwidth == 0 + || $this->resampledheight == 0 ) + { + return FALSE; + } + + /* check current available memory */ + $memorymax = trim(ini_get("memory_limit")); + switch ( strtolower ($memorymax[strlen($memorymax)-1]) ) + { + case 'g': + $memorymax *= 1024; + case 'm': + $memorymax *= 1024; + case 'k': + $memorymax *= 1024; + } + + /* + * this code is based on analyze if gd.c in php source code + * if you can read C/C++, please check these elements and notify us if you have some ideas + */ + if ( (memory_get_usage() + + ($this->resampledwidth * $this->resampledheight * 5 + $this->resampledheight * 24 + 10000) + + ($this->width * $this->height * 5 + $this->height * 24 + 10000)) + > $memorymax ) + { + return FALSE; + } + + switch ( $this->mime ) + { + case 'image/gif': + if ( (!array_key_exists('GIF Read Support', $gdinfo) || !isset($gdinfo['GIF Read Support'])) + || (!array_key_exists('GIF Create Support', $gdinfo) || !isset($gdinfo['GIF Create Support'])) ) + { + return FALSE; + } + $function = 'imagecreatefromgif'; + break; + case 'image/jpeg': + if ( (!array_key_exists('JPEG Support', $gdinfo) || !isset($gdinfo['JPEG Support'])) + && (!array_key_exists('JPG Support', $gdinfo) || !isset($gdinfo['JPG Support'])) ) + { + return FALSE; + } + $function = 'imagecreatefromjpeg'; + break; + case 'image/png': + if ( !array_key_exists('PNG Support', $gdinfo) || !isset($gdinfo['PNG Support']) ) + { + return FALSE; + } + $function = 'imagecreatefrompng'; + break; + default: + return FALSE; + } + + if ( !is_callable($function) ) + { + return FALSE; + } + + $original = call_user_func_array($function, array(&$fullpath)); + if ( !$original ) + { + return FALSE; + } + + $resampledimage = imagecreatetruecolor($this->resampledwidth, $this->resampledheight); + if ( !$resampledimage ) + { + imagedestroy($original); + return FALSE; + } + + @set_time_limit(ini_get('max_execution_time')); + if ( !ImageCopyResampled($resampledimage, $original, 0, 0, 0, 0, $this->resampledwidth, $this->resampledheight, $this->width, $this->height) ) + { + return FALSE; + } + + imagedestroy($original); + + ob_start(); + + switch ( $this->mime ) + { + case 'image/gif': + imagegif($resampledimage); + break; + case 'image/jpeg': + imagejpeg($resampledimage); + break; + case 'image/png': + imagepng($resampledimage); + break; + case 'image/bmp': + case 'image/x-ms-bmp': + imagepng($resampledimage); + break; + default: + return FALSE; + } + + imagedestroy($resampledimage); + + return ob_get_clean(); + } + + public function getHashedName() + { + return (string) hash(Media::$algorism, "{$this->path}/{$this->name}", FALSE); + } +} ++======= + '.jpeg', + 'image/png' => '.png', + 'image/gif' => '.gif', + ); + + /** + * Media::getCollectionList() + * Gets the list of collections available to the currently logged + * in member + * + * @param boolean $exceptReadOnly + * @return array dirname => display name + */ + static public function getCollectionList($exceptReadOnly = FALSE) + { + global $member, $DIR_MEDIA; + + $collections = array(); + + // add private directory for member + $collections[$member->getID()] = PRIVATE_COLLECTION; + + // add global collections + if ( !is_dir($DIR_MEDIA) ) + { + return $collections; + } + + $dirhandle = opendir($DIR_MEDIA); + while ( $dirname = readdir($dirhandle) ) + { + // only add non-numeric (numeric=private) dirs + if ( @is_dir($DIR_MEDIA . $dirname) && + ($dirname != '.') && + ($dirname != '..') && + ($dirname != self::$thumbdir) && + (!is_numeric($dirname)) ) + { + if ( @is_writable($DIR_MEDIA . $dirname) ) + { + $collections[$dirname] = $dirname; + } + else if ( $exceptReadOnly == FALSE ) + { + $collections[$dirname] = $dirname . ' ' . READ_ONLY_MEDIA_FOLDER; + } + } + } + closedir($dirhandle); + + return $collections; + } + + /** + * Media::getMediaListByCollection() + * Returns an array of MediaObject objects for a certain collection + * + * @param string $collection name of the collection + * @param string $filter filter on filename (defaults to none) + * @return void + */ + static public function getMediaListByCollection($collection, $filter = '') + { + global $CONF, $DIR_MEDIA; + + $filelist = array(); + + // 1. go through all objects and add them to the filelist + $mediadir = $DIR_MEDIA . $collection . '/'; + + // return if dir does not exist + if ( !is_dir($mediadir) ) + { + return $filelist; + } + + $dirhandle = opendir($mediadir); + while ( $filename = readdir($dirhandle) ) + { + // only add files that match the filter + if ( !is_dir($mediadir . $filename) && self::checkFilter($filename, $filter) ) + { + array_push($filelist, new MediaObject($collection, $filename, $DIR_MEDIA)); + } + } + closedir($dirhandle); + + /* sort array */ + if ( !$CONF['MediaPrefix'] ) + { + usort($filelist, array(__CLASS__, 'sort_media_by_timestamp')); + } + else + { + usort($filelist, array(__CLASS__, 'sort_media_by_filename')); + } + + return $filelist; + } + + /** + * Media::checkFilter() + * + * @param string $strText + * @param string $strFilter + * @return boolean + */ + static public function checkFilter($strText, $strFilter) + { + if ( $strFilter == '' ) + { + return 1; + } + else + { + return is_integer(i18n::strpos(strtolower($strText), strtolower($strFilter))); + } + } + + /** + * Media::isValidCollection() + * checks if a collection exists with the given name, and if it's + * allowed for the currently logged in member to upload files to it + * + * @param string $collectionName + * @param string $exceptReadOnly + * @return boolean + */ + static public function isValidCollection($collectionName, $exceptReadOnly = FALSE) + { + global $member, $DIR_MEDIA; + + // allow creating new private directory + if ( $collectionName === (string)$member->getID() ) + { + return TRUE; + } + + $collections = self::getCollectionList($exceptReadOnly); + $dirname = $collections[$collectionName]; + + if ( $dirname == NULL || $dirname === PRIVATE_COLLECTION ) + { + return FALSE; + } + + // other collections should exist and be writable + $collectionDir = $DIR_MEDIA . $collectionName; + if ( $exceptReadOnly ) + { + return ( @is_dir($collectionDir) && @is_writable($collectionDir) ); + } + + // other collections should exist + return @is_dir($collectionDir); + } + + /** + * Media::addMediaObject() + * Adds an uploaded file to the media archive + * + * @param string $collection collection + * @param array $uploadfile the postFileInfo(..) array + * @param string $filename the filename that should be used to save the file as + * (date prefix should be already added here) + * @return string blank if success, message if failed + */ + static public function addMediaObject($collection, $uploadfile, $filename) + { + global $DIR_MEDIA, $manager; + + // clean filename of characters that may cause trouble in a filename using cleanFileName() function from globalfunctions.php + $filename = cleanFileName($filename); + + // should already have tested for allowable types before calling this method. This will only catch files with no extension at all + if ( $filename === FALSE ) + { + return _ERROR_BADFILETYPE; + } + + // trigger PreMediaUpload event + $data = array('collection' => &$collection, 'uploadfile' => $uploadfile, 'filename' => &$filename); + $manager->notify('PreMediaUpload', $data); + + // don't allow uploads to unknown or forbidden collections + $exceptReadOnly = TRUE; + if ( !self::isValidCollection($collection,$exceptReadOnly) ) + { + return _ERROR_DISALLOWED; + } + + // check dir permissions (try to create dir if it does not exist) + $mediadir = $DIR_MEDIA . $collection; + + // try to create new private media directories if needed + if ( !@is_dir($mediadir) && is_numeric($collection) ) + { + $oldumask = umask(0000); + if ( !@mkdir($mediadir, 0777) ) + { + return _ERROR_BADPERMISSIONS; + } + umask($oldumask); + } + + // if dir still not exists, the action is disallowed + if ( !@is_dir($mediadir) ) + { + return _ERROR_DISALLOWED; + } + + if ( !is_writeable($mediadir) ) + { + return _ERROR_BADPERMISSIONS; + } + + // add trailing slash (don't add it earlier since it causes mkdir to fail on some systems) + $mediadir .= '/'; + + if ( file_exists($mediadir . $filename) ) + { + return _ERROR_UPLOADDUPLICATE; + } + + // move file to directory + if ( is_uploaded_file($uploadfile) ) + { + if ( !@move_uploaded_file($uploadfile, $mediadir . $filename) ) + { + return _ERROR_UPLOADMOVEP; + } + } + else + { + if ( !copy($uploadfile, $mediadir . $filename) ) + { + return _ERROR_UPLOADCOPY ; + } + } + + // chmod uploaded file + $oldumask = umask(0000); + @chmod($mediadir . $filename, 0644); + umask($oldumask); + + $data = array('collection' => $collection, 'mediadir' => $mediadir, 'filename' => $filename); + $manager->notify('PostMediaUpload', $data); + + return ''; + } + + /** + * Media::addMediaObjectRaw() + * Adds an uploaded file to the media dir. + * + * NOTE: does not check if $collection is valid. + * + * @param string $collection collection to use + * @param string $filename the filename that should be used to save the file + * as (date prefix should be already added here) + * @param &$data File data (binary) + * @return string blank if success, message if failed + */ + static public function addMediaObjectRaw($collection, $filename, &$data) + { + global $DIR_MEDIA; + + // check dir permissions (try to create dir if it does not exist) + $mediadir = $DIR_MEDIA . $collection; + + // try to create new private media directories if needed + if ( !@is_dir($mediadir) && is_numeric($collection) ) + { + $oldumask = umask(0000); + if ( !@mkdir($mediadir, 0777) ) + { + return _ERROR_BADPERMISSIONS; + } + umask($oldumask); + } + + // if dir still not exists, the action is disallowed + if ( !@is_dir($mediadir) ) + { + return _ERROR_DISALLOWED; + } + + if ( !is_writeable($mediadir) ) + { + return _ERROR_BADPERMISSIONS; + } + + // add trailing slash (don't add it earlier since it causes mkdir to fail on some systems) + $mediadir .= '/'; + + if ( file_exists($mediadir . $filename) ) + { + return _ERROR_UPLOADDUPLICATE; + } + + // create file + $fh = @fopen($mediadir . $filename, 'wb'); + if ( !$fh ) + { + return _ERROR_UPLOADFAILED; + } + $ok = @fwrite($fh, $data); + @fclose($fh); + if ( !$ok ) + { + return _ERROR_UPLOADFAILED; + } + + // chmod uploaded file + $oldumask = umask(0000); + @chmod($mediadir . $filename, 0644); + umask($oldumask); + + return ''; + } + + /** + * Media::responseResampledImage() + * send resampled image via HTTP + * + * @param object $medium MediaObject Object + * @exit + */ + static public function responseResampledImage($medium, $maxwidth=0, $maxheight=0) + { + if ( get_class($medium) !== 'MediaObject' ) + { + header("HTTP/1.1 500 Internal Server Error"); + exit('Nucleus CMS: Fail to generate resampled image'); + return; + } + + $resampledimage = $medium->getResampledBinary($maxwidth, $maxheight); + if ( $resampledimage === FALSE ) + { + unset($resampledimage); + header("HTTP/1.1 503 Service Unavailable"); + exit('Nucleus CMS: Fail to generate resampled image'); + return; + } + + header("Content-type: {$medium->mime}"); + echo $resampledimage; + + unset($resampledimage); + + exit; + } + + /** + * Media::storeResampledImage() + * Store resampled image binary to filesystem as file + * + * @param object $medium MediaObject Object + * @param integer $maxwidth maximum width + * @param integer $maxheight maximum height + * @param string $path directory path for destination + * @param string $name file name for destination + * @return boolean + */ + static public function storeResampledImage($medium, $maxwidth=0, $maxheight=0, $path='', $name='') + { + global $DIR_MEDIA; + + if ( get_class($medium) !== 'MediaObject' ) + { + return FALSE; + } + + if ( $path !== '' ) + { + $path = realpath($path); + if ( !file_exists($path) + || strpos($path, $DIR_MEDIA) !== 0 ) + { + return FALSE; + } + } + else + { + $path = '$DIR_MEDIA/' . self::$thumbdir; + } + + if ( $name === '' ) + { + $name = $medium->getHashedname(); + } + + $resampledimage = $medium->getResampledBinary($maxwidth, $maxheight); + if ( !$resampledimage ) + { + unset($resampledimage); + return FALSE; + } + + $handle = @fopen("{$path}/{$name}", 'w'); + if ( !$handle ) + { + unset ($resampledimage); + return FALSE; + } + + if ( !@fwrite($handle, $resampledimage) ) + { + unset($resampledimage); + @unlink("{$path}/{$name}"); + return FALSE; + } + + unset($resampledimage); + fclose($handle); + + if ( !@chmod("{$path}/{$name}", 0774) ) + { + @unlink("{$path}/{$name}"); + return FALSE; + } + + return TRUE; + } + + /** + * Media::sort_media_by_timestamp() + * User-defined sort method to sort an array of MediaObjects + * + * @param object $a + * @param object $b + * @return boolean + */ + static private function sort_media_by_timestamp($a, $b) + { + if ($a->timestamp == $b->timestamp) return 0; + return ($a->timestamp > $b->timestamp) ? -1 : 1; + } + + /** + * Media::sort_media_by_filename() + * User-defined sort method to sort an array of MediaObjects + * + * @param object $a + * @param object $b + * @return boolean + */ + static private function sort_media_by_filename($a, $b) + { + if ($a->filename == $b->filename) return 0; + return ($a->filename > $b->filename) ? -1 : 1; + } + } + + class MediaObject + { + public $mime = ''; + + public $root = ''; + public $path = ''; + public $private; + public $collection; + public $filename = ''; + + public $prefix = ''; + public $name = ''; + public $suffix = ''; + + public $timestamp = 0; + public $size = 0; + + public $width = 0; + public $height = 0; + public $resampledwidth = 0; + public $resampledheight = 0; + + /** + * MediaObject::__construct() + * + * @param string $collection + * @param string $filename + * @param string $root fullpath to media directory + */ + public function __construct($collection, $filename, $root=0) + { + global $CONF, $DIR_MEDIA; + + /* for backward compatibility */ + if ( is_numeric($root) ) + { + $root = $DIR_MEDIA; + } + + $root = preg_replace('#/*$#', '', $root); + + /* get and validate fullpath for the medium */ + if ( !file_exists($root) + || FALSE === ($fullpath = realpath("{$root}/{$collection}/{$filename}")) + || strpos($fullpath, $root) !== 0 + || !file_exists($fullpath) ) + { + return FALSE; + } + + /* store fundamentals */ + $this->root = $root; + $this->private = (integer) $collection; + $this->collection = $collection; + $this->filename = basename($fullpath); + $this->timestamp = filemtime($fullpath); + + /* store relative directory path from root directory for media */ + $this->path = preg_replace(array("#{$this->root}/#", "#/{$this->filename}#"), '', $fullpath); + if ( $this->path === $this->name ) + { + $this->path = ''; + } + + return; + } + + /** + * MediaObject::refine() + * refine data + * + * @param void + * @return void + */ + public function refine() + { + global $CONF; + + /* store size (byte order) */ + $this->size = filesize("{$this->root}/{$this->path}/{$this->filename}"); + + /* get width and height if this is image binary */ + if ( FALSE === ($info = @getimagesize ("{$this->root}/{$this->path}/{$this->filename}")) ) + { + $this->mime = 'application/octet-stream'; + $this->width = 0; + $this->height = 0; + } + else + { + $this->mime = $info['mime']; + $this->width = $info[0]; + $this->height = $info[1]; + } + + /* utilise Fileinfo subsystem if available */ + if ( defined('FILEINFO_MIME_TYPE') && function_exists ('finfo_open') + && (FALSE !== ($info = finfo_open(FILEINFO_MIME_TYPE))) ) + { + $this->mime = finfo_file($info, "{$this->root}/{$this->path}/{$this->filename}"); + } + + /* store data with parsed filename */ + if ( preg_match('#^(.*)\.([a-zA-Z0-9]{2,})$#', $this->filename, $info) === 1 ) + { + $this->name = $info[1]; + $this->suffix = $info[2]; + + if ( $CONF['MediaPrefix'] && preg_match('#^([0-9]{8})\-(.*)$#', $this->name, $info) == 1 ) + { + $this->prefix = preg_replace('#^([0-9]{4})([0-9]{2})([0-9]{2})$#', '$1/$2/$3', $info[1]); + $this->name = $info[2]; + } + } + + return; + } + + /** + * MediaObject::setResampledSize() + * Set resampled size + * + * @param integer $maxwidth + * @param integer $maxheight + * @return boolean + */ + public function setResampledSize($maxwidth=0, $maxheight=0) + { + if ( ($maxwidth == 0) && ($maxheight == 0) ) + { + return FALSE; + } + else if ( $this->width == 0 || $this->height == 0 ) + { + return FALSE; + } + else if ($this->width < $maxwidth && $this->height < $maxheight ) + { + $this->resampledwidth = $this->width; + $this->resampledheight = $this->height; + } + else if ( $maxheight == 0 || $this->width > $this->height ) + { + $this->resampledheight = intval ($this->height * $maxwidth / $this->width); + $this->resampledwidth = $maxwidth; + } + else if ( $maxwidth == 0 || $this->width <= $this->height ) + { + $this->resampledwidth = intval ($this->width * $maxheight / $this->height); + $this->resampledheight = $maxheight; + } + return TRUE; + } + + /** + * MediaObject::getResampledBinary() + * Return resampled image binary + * + * @param void + * @return mixed binary if success, FALSE if failed + */ + public function getResampledBinary($maxwidth=0, $maxheight=0) + { + static $gdinfo = array(); + static $original; + static $resampledimage; + + if ( !$this->setResampledSize($maxwidth, $maxheight) ) + { + return FALSE; + } + + if ( $gdinfo = array() ) + { + $gdinfo = gd_info(); + } + + if ( $this->path !== '' ) + { + $fullpath = "{$this->root}/{$this->path}/{$this->name}"; + } + else + { + $fullpath = "{$this->root}/{$this->name}"; + } + if ( !file_exists($fullpath) ) + { + return FALSE; + } + + if ( !array_key_exists($this->mime, Media::$image_mime) + || $this->width == 0 + || $this->height == 0 + || $this->resampledwidth == 0 + || $this->resampledheight == 0 ) + { + return FALSE; + } + + /* check current available memory */ + $memorymax = trim(ini_get("memory_limit")); + switch ( strtolower ($memorymax[strlen($memorymax)-1]) ) + { + case 'g': + $memorymax *= 1024; + case 'm': + $memorymax *= 1024; + case 'k': + $memorymax *= 1024; + } + + /* + * this code is based on analyze if gd.c in php source code + * if you can read C/C++, please check these elements and notify us if you have some ideas + */ + if ( (memory_get_usage() + + ($this->resampledwidth * $this->resampledheight * 5 + $this->resampledheight * 24 + 10000) + + ($this->width * $this->height * 5 + $this->height * 24 + 10000)) + > $memorymax ) + { + return FALSE; + } + + switch ( $this->mime ) + { + case 'image/gif': + if ( (!array_key_exists('GIF Read Support', $gdinfo) || !isset($gdinfo['GIF Read Support'])) + || (!array_key_exists('GIF Create Support', $gdinfo) || !isset($gdinfo['GIF Create Support'])) ) + { + return FALSE; + } + $function = 'imagecreatefromgif'; + break; + case 'image/jpeg': + if ( (!array_key_exists('JPEG Support', $gdinfo) || !isset($gdinfo['JPEG Support'])) + && (!array_key_exists('JPG Support', $gdinfo) || !isset($gdinfo['JPG Support'])) ) + { + return FALSE; + } + $function = 'imagecreatefromjpeg'; + break; + case 'image/png': + if ( !array_key_exists('PNG Support', $gdinfo) || !isset($gdinfo['PNG Support']) ) + { + return FALSE; + } + $function = 'imagecreatefrompng'; + break; + default: + return FALSE; + } + + if ( !is_callable($function) ) + { + return FALSE; + } + + $original = call_user_func_array($function, $fullpath); + if ( !$original ) + { + return FALSE; + } + + $resampledimage = imagecreatetruecolor($this->resampledwidth, $this->resampledheight); + if ( !$resampledimage ) + { + imagedestroy($original); + return FALSE; + } + + @set_time_limit(ini_get('max_execution_time')); + if ( !ImageCopyResampled($resampledimage, $original, 0, 0, 0, 0, $this->resampledwidth, $this->resampledheight, $this->width, $this->height) ) + { + return FALSE; + } + + imagedestroy($original); + + ob_start(); + + switch ( $this->mime ) + { + case 'image/gif': + imagegif($resampledimage); + break; + case 'image/jpeg': + imagejpeg($resampledimage); + break; + case 'image/png': + imagepng($resampledimage); + break; + case 'image/bmp': + case 'image/x-ms-bmp': + imagepng($resampledimage); + break; + default: + return FALSE; + } + + imagedestroy($resampledimage); + + return ob_get_clean(); + } + + public function getHashedName() + { + return (string) hash(Media::$algorism, "{$this->path}/{$this->name}", FALSE); + } + } ++>>>>>>> skinnable-master diff --combined nucleus/libs/MEMBER.php index 8172d43,a0a1146..1047d78 --- a/nucleus/libs/MEMBER.php +++ b/nucleus/libs/MEMBER.php @@@ -1,1320 -1,1351 +1,2674 @@@ ++<<<<<<< HEAD +readFromName($displayname); + return $mem; + } + + /** + * Member::createFromID() + * Create a member object for a given ID + * + * @static + * @param Integer $id id for member + */ + public static function &createFromID($id) + { + $mem = new Member(); + $mem->readFromID($id); + return $mem; + } + + /** + * Member::readFromName() + * Read member table in database + * + * @param String $displayname login name + * @return Object SQL resource + * + */ + public function readFromName($displayname) + { + return $this->read('mname='.DB::quoteValue($displayname)); + } + + /** + * Member::readFromID() + * Read member table in database + * + * @param Integer $id id for member + * @return Object SQL resource + * + */ + public function readFromID($id) + { + return $this->read("mnumber=" . intval($id)); + } + + /** + * Member::hash() + * hash the target string + * + * @param String $string target string + * @return Void hashed string + */ + public function hash($string) + { + switch ( $this->algorism ) + { + case 'md5': + default: + $string = md5($string); + } + return $string; + } + + /** + * Member::set_cookie_salt() + * + * @param integer $key secureCookieKey value + * @return void + * + */ + private function set_cookie_salt($key = 0) + { + if ( !$key ) + { + $key = 24; + } + + switch( $key ) + { + case 8: + $this->cookie_salt = preg_replace('/\.[0-9]+\.[0-9]+\.[0-9]+$/', '', serverVar('REMOTE_ADDR')); + break; + case 16: + $this->cookie_salt = preg_replace('/\.[0-9]+\.[0-9]+$/', '', serverVar('REMOTE_ADDR')); + break; + case 24: + $this->cookie_salt = preg_replace('/\.[0-9]+$/', '', serverVar('REMOTE_ADDR')); + break; + case 32: + $this->cookie_salt = serverVar('REMOTE_ADDR'); + break; + default: + $this->cookie_salt = 'none'; + } + return; + } + + /** + * Member::login() + * Tries to login as a given user. + * Returns true when succeeded, returns false when failed + * 3.40 adds CustomLogin event + * + * @param String $login login name for member + * @param String $password password for member + * @param Integer $shared whether the user agent is shared or not + * + */ + public function login($login, $password, $shared=1) + { + global $CONF, $errormessage, $manager; + + /* TODO: validation for $login, $password, $shared */ + if ( $login == '' || $password == '' ) + { + return 0; + } + /* limiting the length of password to avoid hash collision */ + $password=i18n::substr($password, 0, 40); + + /* + * generate cookie salt from secure cookie key settings + * (either 'none', 0, 8, 16, 24, or 32) + */ + if ( !$this->cookie_salt ) + { + $salt = 0; + if ( array_key_exists('secureCookieKey', $CONF) ) + { + $salt = $CONF['secureCookieKey']; + } + $this->set_cookie_salt($salt); + } + + $success = 0; + $allowlocal = 1; + $manager->notify('CustomLogin', array('login' => &$login, 'password'=>&$password, 'success'=>&$success, 'allowlocal'=>&$allowlocal)); + + $this->loggedin = 0; + if ( $success ) + { + $this->loggedin = ( $this->readFromName($login) ); + } + elseif ( $allowlocal ) + { + $this->loggedin = ( $this->readFromName($login) && $this->checkPassword($password) ); + } + + /* login failed */ + if ( !$this->loggedin ) + { + $trimlogin = trim($login); + if ( empty($trimlogin) ) + { + $errormessage = "Please enter a username."; + } + else + { + $errormessage = 'Login failed for ' . $login; + } + $manager->notify('LoginFailed', array('username' => $login) ); + ActionLog::add(INFO, $errormessage); + } + /* login success */ + else + { + /* For lower compatibility */ + if ( strlen($this->password) === 32 ) + { + $this->password = $this->hash($password); + } + + $this->newCookieKey(); + $this->setCookies($shared); + + if ( $this->cookie_salt !== 'none' ) + { + /* secure cookie key */ + $this->setCookieKey($this->hash($this->getCookieKey() . $this->cookie_salt)); + $this->write(); + } + + $errormessage = ''; + $manager->notify('LoginSuccess', array('member' => &$member, 'username' => $login) ); + ActionLog::add(INFO, "Login successful for $login (sharedpc=$shared)"); + } + + return $this->loggedin; + } + + /** + * Member::cookielogin() + * Login using cookie key + * + * @param String $login not used + * @param String $cookiekey not used + * @return Boolean login or not + */ + public function cookielogin($login='', $cookiekey='') + { + global $CONF, $manager; + + if ( !headers_sent() && cookieVar("{$CONF['CookiePrefix']}user") ) + { + /* Cookie Authentication */ + $ck = cookieVar("{$CONF['CookiePrefix']}loginkey"); + + /* TODO: validation for each cookie values */ + + /* limiting the length of password to avoid hash collision */ + $ck = i18n::substr($ck,0,32); + + /* + * generate cookie salt from secure cookie key settings + * (either 'none', 0, 8, 16, 24, or 32) + */ + if ( !$this->cookie_salt ) + { + $salt = 0; + if ( array_key_exists('secureCookieKey', $CONF) ) + { + $salt = $CONF['secureCookieKey']; + } + $this->set_cookie_salt($salt); + } + + if ( $this->cookie_salt !== 'none' ) + { + $ck = $this->hash($ck . $this->cookie_salt); + } + $this->loggedin = ( $this->readFromName(cookieVar("{$CONF['CookiePrefix']}user")) && $this->checkCookieKey($ck) ); + unset($ck); + + /* renew cookies when not on a shared computer */ + if ( $this->loggedin && (cookieVar($CONF['CookiePrefix'] . 'sharedpc') != 1) ) + { + $this->setCookieKey(cookieVar("{$CONF['CookiePrefix']}loginkey")); + $this->setCookies(); + } + } + return $this->loggedin; + } + + /** + * Member::logout() + * logout and expire cookie + * + * @param Void + * @return Void + */ + public function logout() + { + global $CONF, $manager; + + if ( !headers_sent() && cookieVar("{$CONF['CookiePrefix']}user") ) + { + /* remove cookies on logout */ + setcookie("{$CONF['CookiePrefix']}user", '', (time() - 2592000), $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + setcookie("{$CONF['CookiePrefix']}loginkey", '', (time() - 2592000), $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + $manager->notify('Logout', array('username' => cookieVar("{$CONF['CookiePrefix']}user") ) ); + } + + $this->loggedin = 0; + return; + } + + /** + * Member::isLoggedIn() + * return member is loggedin or not + * + * @param Void + * @return Void + */ + public function isLoggedIn() + { + return $this->loggedin; + } + + /** + * MEMBER:read() + * Read member information from the database + * + * @param String $where where statement + * @return Resource SQL resource + * + */ + public function read($where) + { + // read info + $query = 'SELECT * FROM '.sql_table('member') . ' WHERE ' . $where; + + $row = DB::getRow($query); + + $this->setRealName($row['mrealname']); + $this->setEmail($row['memail']); + $this->password = $row['mpassword']; + $this->setCookieKey($row['mcookiekey']); + $this->setURL($row['murl']); + $this->setDisplayName($row['mname']); + $this->setAdmin($row['madmin']); + $this->id = $row['mnumber']; + $this->setCanLogin($row['mcanlogin']); + $this->setNotes($row['mnotes']); + $this->setLocale($row['mlocale']); + $this->setAutosave($row['mautosave']); + + return $row ? TRUE : FALSE; + } + + /** + * Member::isBlogAdmin() + * Returns true if member is an admin for the given blog + * (returns false if not a team member) + * + * @param Integer $blogid weblog id + * @return Integer weblog admin or not + * + */ + public function isBlogAdmin($blogid) + { + $query = 'SELECT tadmin FROM '.sql_table('team').' WHERE' + . ' tblog=' . intval($blogid) + . ' and tmember='. $this->getID(); + $res = DB::getValue($query); + if ( $res ) + return ($res == 1); + else + return 0; + } + + /** + * Member::blogAdminRights() + * + * @param integer $blogid ID of target weblog + * @return boolean whether to have admin rights to the weblog or not + * + */ + public function blogAdminRights($blogid) + { + return ($this->isAdmin() || $this->isBlogAdmin($blogid)); + } + + /** + * Member::teamRights() + * + * @param integer $blogid ID of target weblog + * @return boolean whether to have admin right to the weblog or not + * + */ + public function teamRights($blogid) + { + return ($this->isAdmin() || $this->isTeamMember($blogid)); + } + + /** + * Member::isTeamMember() + * Returns true if this member is a team member of the given blog + * + * @param integer $blogid ID of target weblog + * @return boolean whether to join the weblog or not + * + */ + public function isTeamMember($blogid) + { + $query = 'SELECT * FROM '.sql_table('team').' WHERE' + . ' tblog=' . intval($blogid) + . ' and tmember='. $this->getID(); + $res = DB::getResult($query); + return ($res->rowCount() != 0); + } + + /** + * Member::canAddItem() + * + * @param integer $catid ID of target category + * @return boolean whether to be able to add items to the category or not + * + */ + public function canAddItem($catid) + { + global $manager; + + // if this is a 'newcat' style newcat + // no blog admin of destination blog -> NOK + // blog admin of destination blog -> OK + if ( i18n::strpos($catid,'newcat') === 0 ) + { + // get blogid + list($blogid) = sscanf($catid,"newcat-%d"); + return $this->blogAdminRights($blogid); + } + + // category does not exist -> NOK + if ( !$manager->existsCategory($catid) ) + { + return 0; + } + + $blogid = getBlogIDFromCatID($catid); + + // no team rights for blog -> NOK + if (!$this->teamRights($blogid)) + { + return 0; + } + + // all other cases: OK + return 1; + } + + /** + * Member::canAlterComment() + * Returns true if this member can edit/delete a commentitem. This can be in the + * following cases: + * - member is a super-admin + * - member is the author of the comment + * - member is admin of the blog associated with the comment + * - member is author of the item associated with the comment + * + * @param integer $commentid ID of target comment + * @return boolean delete/edit the comment or not + * + */ + public function canAlterComment($commentid) + { + if ( $this->isAdmin() ) + { + return 1; + } + + $query = 'SELECT citem as itemid, iblog as blogid, cmember as cauthor, iauthor' + . ' FROM '.sql_table('comment') .', '.sql_table('item').', '.sql_table('blog') + . ' WHERE citem=inumber and iblog=bnumber and cnumber=' . intval($commentid); + $res = DB::getRow($query); + + return ($res['cauthor'] == $this->getID()) or $this->isBlogAdmin($res['blogid']) or ($res['iauthor'] == $this->getID()); + } + + /** + * Member::canAlterItem() + * Returns true if this member can edit/delete an item. This is true in the following + * cases: - member is a super-admin + * - member is the author of the item + * - member is admin of the the associated blog + * + * @param integer $itemid ID of target item + * @return boolean delete/edit the item or not + * + */ + public function canAlterItem($itemid) + { + if ($this->isAdmin()) return 1; + + $query = 'SELECT iblog, iauthor FROM '.sql_table('item').' WHERE inumber=' . intval($itemid); + $res = DB::getRow($query); + return ($res['iauthor'] == $this->getID()) or $this->isBlogAdmin($res['iblog']); + } + + /** + * Member::canBeDeleted() + * Return true if member can be deleted. This means that there are no items posted by the member left + * + * @param void + * @return boolean whether there is no items or exists + * + */ + public function canBeDeleted() + { + $res = DB::getResult('SELECT * FROM '.sql_table('item').' WHERE iauthor=' . $this->getID()); + return ( $res->rowCount() == 0 ); + } + + /** + * Member::canUpdateItem() + * returns true if this member can move/update an item to a given category, + * false if not (see comments fot the tests that are executed) + * + * @param integer $itemid + * @param string $newcat (can also be of form 'newcat-x' with x=blogid) + * @return boolean whether being able to update the item or not + * + */ + public function canUpdateItem($itemid, $newcat) + { + global $manager; + + // item does not exists -> NOK + if ( !$manager->existsItem($itemid,1,1) ) + { + return 0; + } + + // cannot alter item -> NOK + if (!$this->canAlterItem($itemid)) + { + return 0; + } + + // if this is a 'newcat' style newcat + // no blog admin of destination blog -> NOK + // blog admin of destination blog -> OK + if ( i18n::strpos($newcat, 'newcat') === 0 ) + { + // get blogid + list($blogid) = sscanf($newcat, 'newcat-%d'); + return $this->blogAdminRights($blogid); + } + + // category does not exist -> NOK + if (!$manager->existsCategory($newcat)) + { + return 0; + } + + // get item + $item =& $manager->getItem($itemid,1,1); + + // old catid = new catid -> OK + if ($item['catid'] == $newcat) + { + return 1; + } + + // not a valid category -> NOK + $validCat = DB::getValue('SELECT COUNT(*) AS result FROM '.sql_table('category').' WHERE catid='.intval($newcat)); + if ( !$validCat ) + { + return 0; + } + + // get destination blog + $source_blogid = getBlogIDFromItemID($itemid); + $dest_blogid = getBlogIDFromCatID($newcat); + + // not a team member of destination blog -> NOK + if ( !$this->teamRights($dest_blogid) ) + { + return 0; + } + + // if member is author of item -> OK + if ( $item['authorid'] == $this->getID() ) + { + return 1; + } + + // if member has admin rights on both blogs: OK + if ( ($this->blogAdminRights($dest_blogid)) && ($this->blogAdminRights($source_blogid)) ) + { + return 1; + } + + // all other cases: NOK + return 0; + } + + /** + * Member::setCookies() + * Sets the cookies for the member + * + * @param boolean $shared set this to 1 when using a shared computer. Cookies will expire + * at the end of the session in this case. + * @return void + * + */ + public function setCookies($shared = 0) + { + global $CONF; + + if ( $CONF['SessionCookie'] || $shared ) + { + $lifetime = 0; + } + else + { + $lifetime = time()+2592000; + } + + setcookie($CONF['CookiePrefix'] . 'user', $this->getDisplayName(), $lifetime, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + setcookie($CONF['CookiePrefix'] . 'loginkey', $this->getCookieKey(), $lifetime, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + + // make sure cookies on shared pcs don't get renewed + if ( $shared ) + { + setcookie($CONF['CookiePrefix'] .'sharedpc', '1',$lifetime,$CONF['CookiePath'],$CONF['CookieDomain'],$CONF['CookieSecure']); + } + return; + } + + /** + * Member::sendActivationLink() + * Send activation mail + * + * @param string $type activation type + * @param string $extra extra info + * @return void + */ + public function sendActivationLink($type, $extra='') + { + global $CONF; + + if ( !isset($CONF['ActivationDays']) ) + { + $CONF['ActivationDays'] = 2; + } + + // generate key and URL + $key = $this->generateActivationEntry($type, $extra); + $url = $CONF['AdminURL'] . 'index.php?action=activate&key=' . $key; + + // choose text to use in mail + switch ( $type ) + { + case 'register': + $message = _ACTIVATE_REGISTER_MAIL; + $subject = _ACTIVATE_REGISTER_MAILTITLE; + break; + case 'forgot': + $message = _ACTIVATE_FORGOT_MAIL; + $subject = _ACTIVATE_FORGOT_MAILTITLE; + break; + case 'addresschange': + $message = _ACTIVATE_CHANGE_MAIL; + $subject = _ACTIVATE_CHANGE_MAILTITLE; + break; + default; + } + + // fill out variables in text + $aVars = array( + 'siteName' => $CONF['SiteName'], + 'siteUrl' => $CONF['IndexURL'], + 'memberName' => $this->getDisplayName(), + 'activationUrl' => $url, + 'activationDays' => $CONF['ActivationDays'] + ); + + $message = Template::fill($message, $aVars); + $subject = Template::fill($subject, $aVars); + + // send mail + NOTIFICATION::mail($this->getEmail(), $subject ,$message, $CONF['AdminEmail'], i18n::get_current_charset()); + + ActionLog::add(INFO, _ACTIONLOG_ACTIVATIONLINK . ' (' . $this->getDisplayName() . ' / type: ' . $type . ')'); + return; + } + + /** + * Member::getAdminBlogs() + * Returns an array of all blogids for which member has admin rights + * + * @param void + * @return array weblog IDs in which this member has admin rights + * + */ + public function getAdminBlogs() + { + $blogs = array(); + + if ($this->isAdmin()) + { + $query = 'SELECT bnumber as blogid from '.sql_table('blog'); + } + else + { + $query = 'SELECT tblog as blogid from '.sql_table('team').' where tadmin=1 and tmember=' . $this->getID(); + } + + $res = DB::getResult($query); + if ( $res->rowCount() > 0 ) + { + foreach ( $res as $row ) + { + array_push($blogs, $row['blogid']); + } + } + return $blogs; + } + + /** + * Member::getTeamBlogs() + * Returns an array of all blogids for which member has team rights + * + * @param boolean $incAdmin whether checking weblog admin rights or not + * @return array weblog IDs in which this member join + * + */ + public function getTeamBlogs($incAdmin = 1) + { + $incAdmin = intval($incAdmin); + $blogs = array(); + + if ( $this->isAdmin() && $incAdmin ) + { + $query = 'SELECT bnumber as blogid from '.sql_table('blog'); + } + else + { + $query = 'SELECT tblog as blogid from '.sql_table('team').' where tmember=' . $this->getID(); + } + + $res = DB::getResult($query); + if ( $res->rowCount() > 0 ) + { + foreach ( $res as $row ) + { + array_push($blogs, $row['blogid']); + } + } + return $blogs; + } + + /** + * Member::getNotifyFromMailAddress() + * + * Returns an email address from which notification of commenting/karma voting can + * be sent. A suggestion can be given for when the member is not logged in + * + * @param String $suggest + * @return String mail address or suggestion + */ + public function getNotifyFromMailAddress($suggest = "") + { + global $CONF; + if ( $this->isLoggedIn() ) + { + return $this->getDisplayName() . " <" . $this->getEmail() . ">"; + } + else if ( NOTIFICATION::address_validation($suggest) ) + { + return $suggest; + } + return $CONF['AdminEmail']; + } + + /** + * Member::write() + * Write data to database + * + * @param void + * @return void + * + */ + public function write() + { + $query = 'UPDATE '.sql_table('member') + . ' SET mname=' . DB::quoteValue($this->displayname) . ', ' + . 'mrealname='. DB::quoteValue($this->realname) . ', ' + . 'mpassword='. DB::quoteValue($this->password) . ', ' + . 'mcookiekey='. DB::quoteValue($this->cookiekey) . ', ' + . 'murl=' . DB::quoteValue($this->url) . ', ' + . 'memail=' . DB::quoteValue($this->email) . ', ' + . 'madmin=' . intval($this->admin) . ', ' + . 'mnotes=' . DB::quoteValue($this->notes) . ', ' + . 'mcanlogin=' . intval($this->canlogin) . ', ' + . 'mlocale=' . DB::quoteValue($this->locale) . ', ' + . 'mautosave=' . intval($this->autosave) . ' ' + . 'WHERE mnumber=' . intval($this->id); + DB::execute($query); + return; + } + + public function checkCookieKey($key) + { + return ( ($key != '') && ( $key == $this->getCookieKey() ) ); + } + + public function checkPassword($pw) + { + /* for lower compatibility (md5) */ + if ( strlen($this->password) === 32 ) + { + return (md5($pw) == $this->password); + } + return ($this->hash($pw) == $this->password); + } + + public function getRealName() + { + return $this->realname; + } + + public function setRealName($name) + { + $this->realname = $name; + } + + public function getEmail() + { + return $this->email; + } + + public function setEmail($email) + { + $this->email = $email; + } + + public function getPassword() + { + return $this->password; + } + + public function setPassword($pwd) + { + $this->password = $this->hash($pwd); + } + + public function getCookieKey() + { + return $this->cookiekey; + } + + /** + * Member::newCookieKey() + * Generate new cookiekey, save it, and return it + * + * @param void + * @return void + * + */ + public function newCookieKey() + { + mt_srand( (double) microtime() * 1000000); + $this->cookiekey = $this->hash(uniqid(mt_rand())); + $this->write(); + return $this->cookiekey; + } + + public function setCookieKey($val) + { + $this->cookiekey = $val; + } + + public function getURL() + { + return $this->url; + } + + public function setURL($site) + { + $this->url = $site; + } + + public function getLocale() + { + return $this->locale; + } + + public function setLocale($locale) + { + if ( !preg_match('#^(.+)_(.+)_(.+)$#', $locale) + && ($locale = i18n::convert_old_language_file_name_to_locale($locale)) === FALSE ) + { + $locale = ''; + } + $this->locale = $locale; + return; + } + + public function setDisplayName($nick) + { + $this->displayname = $nick; + } + + public function getDisplayName() + { + return $this->displayname; + } + + public function isAdmin() + { + return $this->admin; + } + + public function setAdmin($val) + { + $this->admin = $val; + } + + public function canLogin() + { + return $this->canlogin; + } + + public function setCanLogin($val) + { + $this->canlogin = $val; + } + + public function getNotes() + { + return $this->notes; + } + + public function setNotes($val) + { + $this->notes = $val; + } + + public function getAutosave() + { + return $this->autosave; + } + + public function setAutosave($val) + { + $this->autosave = $val; + return; + } + + /** + * Member::getID() + * + * @param void + * @return integer id of this member object + * + */ + public function getID() + { + return $this->id; + } + + /** + * Member::exists() + * Returns true if there is a member with the given login name + * + * @static + * @param string $name target name + * @return boolean whether target name exists or not + */ + public static function exists($name) + { + $r = DB::getResult('SELECT * FROM ' . sql_table('member') . ' WHERE mname=' . DB::quoteValue($name)); + return ( $r->rowCount() != 0 ); + } + + /** + * Member::existsID() + * Returns true if there is a member with the given ID + * + * @static + * @param integer $id target id + * @return boolean whether target id exists or not + * + */ + public static function existsID($id) + { + $r = DB::getResult('SELECT * FROM ' . sql_table('member') . ' WHERE mnumber=' . intval($id)); + return ( $r->rowCount() != 0 ); + } + + /** + * Member::isNameProtected() + * Checks if a username is protected. + * If so, it can not be used on anonymous comments + * + * @param string $name target name + * @return boolean whether the name exists or not + * + */ + public function isNameProtected($name) + { + // extract name + $name = strip_tags($name); + $name = trim($name); + return self::exists($name); + } + + /** + * Member::create() + * Adds a new member + * + * @static + * @param String $name + * @param String $realname + * @param String $password + * @param String $email + * @param String $url + * @param String $admin + * @param String $canlogin + * @param String $notes + * @return String 1 if success, others if fail + */ + static public function create($name, $realname, $password, $email, $url, $admin, $canlogin, $notes) + { + if ( !NOTIFICATION::address_validation($email) ) + { + return _ERROR_BADMAILADDRESS; + } + + /* TODO: this method should be in MEMBER class, not globalfunctions */ + if ( !isValidDisplayName($name) ) + { + return _ERROR_BADNAME; + } + + if ( self::exists($name) ) + { + return _ERROR_NICKNAMEINUSE; + } + + if ( !$realname ) + { + return _ERROR_REALNAMEMISSING; + } + + /* TODO: check the number of characters */ + if ( !$password ) + { + return _ERROR_PASSWORDMISSING; + } + + /* + * begin if: sometimes user didn't prefix the URL with http:// or https://, + * this cause a malformed URL. Let's fix it. + */ + + if ( !preg_match('#^https?://#', $url) ) + { + $url = 'http://' . $url; + } + + $name = DB::quoteValue($name); + $realname = DB::quoteValue($realname); + /* NOTE: hashed password is automatically updated if the length is 32 bytes when logging in */ + $password = DB::quoteValue(md5($password)); + $email = DB::quoteValue($email); + $url = DB::quoteValue($url); + $admin = (integer) $admin; + $canlogin = (integer) $canlogin; + $notes = DB::quoteValue($notes); + + $query = "INSERT INTO %s" + . " (MNAME,MREALNAME,MPASSWORD,MEMAIL,MURL, MADMIN, MCANLOGIN, MNOTES)" + . " VALUES (%s, %s, %s, %s, %s, %d, %d, %s)"; + $query = sprintf($query, sql_table('member'), $name, $realname, $password, $email, $url, $admin, $canlogin, $notes); + DB::execute($query); + + ActionLog::add(INFO, _ACTIONLOG_NEWMEMBER . ' ' . $name); + + return 1; + } + + /** + * Member::getActivationInfo() + * Returns activation info for a certain key (an object with properties vkey, vmember, ...) + * + * @static + * @param string $key activation key + * @return mixed return 0 if failed, else return activation table object + * + */ + public static function getActivationInfo($key) + { + $query = 'SELECT * FROM ' . sql_table('activation') . ' WHERE vkey=' . DB::quoteValue($key); + $res = DB::getResult($query); + + if ( !$res || ($res->rowCount() == 0) ) + { + return 0; + } + return $res->fetch(); + } + + /** + * Member::generateActivationEntry() + * Creates an account activation key + * addresschange -> old email address + * + * @param string $type one of the following values (determines what to do when activation expires) + * 'register' (new member registration) + * 'forgot' (forgotton password) + * 'addresschange' (member address has changed) + * @param string $extra extra info (needed when validation link expires) + * @return string activation key + */ + public function generateActivationEntry($type, $extra = '') + { + // clean up old entries + $this->cleanupActivationTable(); + + // kill any existing entries for the current member (delete is ok) + // (only one outstanding activation key can be present for a member) + DB::execute('DELETE FROM ' . sql_table('activation') . ' WHERE vmember=' . intval($this->getID())); + + // indicates if the member can log in while the link is active + $canLoginWhileActive = false; + switch ( $type ) + { + case 'forgot': + $canLoginWhileActive = true; + break; + case 'register': + break; + case 'addresschange': + $extra = $extra . '/' . ( $this->canLogin() ? '1' : '0' ); + break; + } + + $ok = false; + while ( !$ok ) + { + // generate a random key + srand((double)microtime()*1000000); + $key = $this->hash(uniqid(rand(), true)); + + // attempt to add entry in database + // add in database as non-active + $query = 'INSERT INTO %s (vkey, vtime, vmember, vtype, vextra) VALUES (%s, %s, %d, %s, %s)'; + $query = sprintf($query + , sql_table('activation') + , DB::quoteValue($key) + , DB::formatDateTime() + , intval($this->getID()) + , DB::quoteValue($type) + , DB::quoteValue($extra) + ); + if ( DB::execute($query) !== FALSE ) + $ok = true; + } + + // mark member as not allowed to log in + if ( !$canLoginWhileActive ) + { + $this->setCanLogin(0); + $this->write(); + } + + // return the key + return $key; + } + + /** + * Member::activate() + * Inidicates that an activation link has been clicked and any forms displayed + * there have been successfully filled out. + * + * @param string $key activation key + * @return boolean + * + */ + public function activate($key) + { + // get activate info + $info = self::getActivationInfo($key); + + // no active key + if ( !$info ) + { + return false; + } + + switch ( $info['vtype'] ) + { + case 'forgot': + // nothing to do + break; + case 'register': + // set canlogin value + global $CONF; + DB::execute('UPDATE ' . sql_table('member') . ' SET mcanlogin=' . intval($CONF['NewMemberCanLogon']). ' WHERE mnumber=' . intval($info['vmember'])); + break; + case 'addresschange': + // reset old 'canlogin' value + list($oldEmail, $oldCanLogin) = preg_split('#/#', $info['vextra']); + DB::execute('UPDATE ' . sql_table('member') . ' SET mcanlogin=' . intval($oldCanLogin). ' WHERE mnumber=' . intval($info['vmember'])); + break; + } + + // delete from activation table + DB::execute('DELETE FROM ' . sql_table('activation') . ' WHERE vkey=' . DB::quoteValue($key)); + + // success! + return true; + } + + /** + * Member::cleanupActivationTable() + * Cleans up entries in the activation table. All entries older than 2 days are removed. + * (static) + * + * @param void + * @return void + */ + public function cleanupActivationTable() + { + $actdays = 2; + if ( isset($CONF['ActivationDays']) && intval($CONF['ActivationDays']) > 0 ) + { + $actdays = intval($CONF['ActivationDays']); + } + else + { + $CONF['ActivationDays'] = 2; + } + $boundary = time() - (60 * 60 * 24 * $actdays); + + // 1. walk over all entries, and see if special actions need to be performed + $query = sprintf('SELECT * FROM %s WHERE vtime < %s', sql_table('activation'), DB::formatDateTime($boundary)); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + switch ( $row['vtype'] ) + { + case 'register': + // delete all information about this site member. registration is undone because there was + // no timely activation + include_once($DIR_LIBS . 'ADMIN.php'); + Admin::deleteOneMember(intval($row['vmember'])); + break; + case 'addresschange': + // revert the e-mail address of the member back to old address + list($oldEmail, $oldCanLogin) = preg_split('#/#', $row['vextra']); + DB::execute('UPDATE ' . sql_table('member') . ' SET mcanlogin=' . intval($oldCanLogin). ', memail=' . DB::quoteValue($oldEmail). ' WHERE mnumber=' . intval($row['vmember'])); + break; + case 'forgot': + // delete the activation link and ignore. member can request a new password using the + // forgot password link + break; + } + } + + // 2. delete activation entries for real + $query = sprintf('DELETE FROM %s WHERE vtime < %s', sql_table('activation'), DB::formatDateTime($boundary)); + DB::execute($query); + return; + } + + /** + * Member::$language + * + * @obsolete + * @param void + * @return void + * + */ + public $language = ''; + /** + * Member::getLanguage() + * + * @obsolete + * @param void + * @return void + * + */ + public function getLanguage() + { + if ( ($language = i18n::convert_locale_to_old_language_file_name($this->locale)) === FALSE ) + { + $language = ''; + } + return $language; + } +} ++======= + readFromName($displayname); + return $mem; + } + + /** + * Member::createFromID() + * Create a member object for a given ID + * + * @static + * @param Integer $id id for member + */ + public static function &createFromID($id) + { + $mem = new Member(); + $mem->readFromID($id); + return $mem; + } + + /** + * Member::readFromName() + * Read member table in database + * + * @param String $displayname login name + * @return Object SQL resource + * + */ + public function readFromName($displayname) + { + return $this->read('mname='.DB::quoteValue($displayname)); + } + + /** + * Member::readFromID() + * Read member table in database + * + * @param Integer $id id for member + * @return Object SQL resource + * + */ + public function readFromID($id) + { + return $this->read("mnumber=" . intval($id)); + } + + /** + * Member::hash() + * hash the target string + * + * @param String $string target string + * @return Void hashed string + */ + public function hash($string) + { + switch ( $this->algorism ) + { + case 'md5': + default: + $string = md5($string); + } + return $string; + } + + /** + * Member::set_cookie_salt() + * + * @param integer $key secureCookieKey value + * @return void + * + */ + private function set_cookie_salt($key = 0) + { + if ( !$key ) + { + $key = 24; + } + + switch( $key ) + { + case 8: + $this->cookie_salt = preg_replace('/\.[0-9]+\.[0-9]+\.[0-9]+$/', '', serverVar('REMOTE_ADDR')); + break; + case 16: + $this->cookie_salt = preg_replace('/\.[0-9]+\.[0-9]+$/', '', serverVar('REMOTE_ADDR')); + break; + case 24: + $this->cookie_salt = preg_replace('/\.[0-9]+$/', '', serverVar('REMOTE_ADDR')); + break; + case 32: + $this->cookie_salt = serverVar('REMOTE_ADDR'); + break; + default: + $this->cookie_salt = 'none'; + } + return; + } + + /** + * Member::login() + * Tries to login as a given user. + * Returns true when succeeded, returns false when failed + * 3.40 adds CustomLogin event + * + * @param String $login login name for member + * @param String $password password for member + * @param Integer $shared whether the user agent is shared or not + * + */ + public function login($login, $password, $shared=1) + { + global $CONF, $errormessage, $manager; + + /* TODO: validation for $login, $password, $shared */ + if ( $login == '' || $password == '' ) + { + return 0; + } + /* limiting the length of password to avoid hash collision */ + $password=i18n::substr($password, 0, 40); + + /* + * generate cookie salt from secure cookie key settings + * (either 'none', 0, 8, 16, 24, or 32) + */ + if ( !$this->cookie_salt ) + { + $salt = 0; + if ( array_key_exists('secureCookieKey', $CONF) ) + { + $salt = $CONF['secureCookieKey']; + } + $this->set_cookie_salt($salt); + } + + $success = 0; + $allowlocal = 1; + $data = array('login' => &$login, 'password'=>&$password, 'success'=>&$success, 'allowlocal'=>&$allowlocal); + $manager->notify('CustomLogin', $data); + + $this->loggedin = 0; + if ( $success ) + { + $this->loggedin = ( $this->readFromName($login) ); + } + elseif ( $allowlocal ) + { + $this->loggedin = ( $this->readFromName($login) && $this->checkPassword($password) ); + } + + /* login failed */ + if ( !$this->loggedin ) + { + $trimlogin = trim($login); + if ( empty($trimlogin) ) + { + $errormessage = "Please enter a username."; + } + else + { + $errormessage = 'Login failed for ' . $login; + } + $data = array('username' => $login); + $manager->notify('LoginFailed', $data); + ActionLog::add(INFO, $errormessage); + } + /* login success */ + else + { + /* For lower compatibility */ + if ( strlen($this->password) === 32 ) + { + $this->password = $this->hash($password); + } + + $this->newCookieKey(); + $this->setCookies($shared); + + if ( $this->cookie_salt !== 'none' ) + { + /* secure cookie key */ + $this->setCookieKey($this->hash($this->getCookieKey() . $this->cookie_salt)); + $this->write(); + } + + $errormessage = ''; + $data = array('member' => &$this, 'username' => $login); + $manager->notify('LoginSuccess', $data); + ActionLog::add(INFO, "Login successful for $login (sharedpc=$shared)"); + } + + return $this->loggedin; + } + + /** + * Member::cookielogin() + * Login using cookie key + * + * @param String $login not used + * @param String $cookiekey not used + * @return Boolean login or not + */ + public function cookielogin($login='', $cookiekey='') + { + global $CONF, $manager; + + if ( !headers_sent() && cookieVar("{$CONF['CookiePrefix']}user") ) + { + /* Cookie Authentication */ + $ck = cookieVar("{$CONF['CookiePrefix']}loginkey"); + + /* TODO: validation for each cookie values */ + + /* limiting the length of password to avoid hash collision */ + $ck = i18n::substr($ck,0,32); + + /* + * generate cookie salt from secure cookie key settings + * (either 'none', 0, 8, 16, 24, or 32) + */ + if ( !$this->cookie_salt ) + { + $salt = 0; + if ( array_key_exists('secureCookieKey', $CONF) ) + { + $salt = $CONF['secureCookieKey']; + } + $this->set_cookie_salt($salt); + } + + if ( $this->cookie_salt !== 'none' ) + { + $ck = $this->hash($ck . $this->cookie_salt); + } + $this->loggedin = ( $this->readFromName(cookieVar("{$CONF['CookiePrefix']}user")) && $this->checkCookieKey($ck) ); + unset($ck); + + /* renew cookies when not on a shared computer */ + if ( $this->loggedin && (cookieVar($CONF['CookiePrefix'] . 'sharedpc') != 1) ) + { + $this->setCookieKey(cookieVar("{$CONF['CookiePrefix']}loginkey")); + $this->setCookies(); + } + } + return $this->loggedin; + } + + /** + * Member::logout() + * logout and expire cookie + * + * @param Void + * @return Void + */ + public function logout() + { + global $CONF, $manager; + + if ( !headers_sent() && cookieVar("{$CONF['CookiePrefix']}user") ) + { + /* remove cookies on logout */ + setcookie("{$CONF['CookiePrefix']}user", '', (time() - 2592000), $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + setcookie("{$CONF['CookiePrefix']}loginkey", '', (time() - 2592000), $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + $data = array('username' => cookieVar("{$CONF['CookiePrefix']}user")); + $manager->notify('Logout', $data); + } + + $this->loggedin = 0; + return; + } + + /** + * Member::isLoggedIn() + * return member is loggedin or not + * + * @param Void + * @return Void + */ + public function isLoggedIn() + { + return $this->loggedin; + } + + /** + * MEMBER:read() + * Read member information from the database + * + * @param String $where where statement + * @return Resource SQL resource + * + */ + public function read($where) + { + // read info + $query = 'SELECT * FROM '.sql_table('member') . ' WHERE ' . $where; + + $row = DB::getRow($query); + + $this->setRealName($row['mrealname']); + $this->setEmail($row['memail']); + $this->password = $row['mpassword']; + $this->setCookieKey($row['mcookiekey']); + $this->setURL($row['murl']); + $this->setDisplayName($row['mname']); + $this->setAdmin($row['madmin']); + $this->id = $row['mnumber']; + $this->setCanLogin($row['mcanlogin']); + $this->setNotes($row['mnotes']); + $this->setLocale($row['mlocale']); + $this->setAutosave($row['mautosave']); + $this->setAdminSkin($row['madminskin']); + $this->setBookmarklet($row['mbkmklt']); + + return $row ? TRUE : FALSE; + } + + /** + * Member::isBlogAdmin() + * Returns true if member is an admin for the given blog + * (returns false if not a team member) + * + * @param Integer $blogid weblog id + * @return Integer weblog admin or not + * + */ + public function isBlogAdmin($blogid) + { + $query = 'SELECT tadmin FROM '.sql_table('team').' WHERE' + . ' tblog=' . intval($blogid) + . ' and tmember='. $this->getID(); + $res = DB::getValue($query); + if ( $res ) + return ($res == 1); + else + return 0; + } + + /** + * Member::blogAdminRights() + * + * @param integer $blogid ID of target weblog + * @return boolean whether to have admin rights to the weblog or not + * + */ + public function blogAdminRights($blogid) + { + return ($this->isAdmin() || $this->isBlogAdmin($blogid)); + } + + /** + * Member::teamRights() + * + * @param integer $blogid ID of target weblog + * @return boolean whether to have admin right to the weblog or not + * + */ + public function teamRights($blogid) + { + return ($this->isAdmin() || $this->isTeamMember($blogid)); + } + + /** + * Member::isTeamMember() + * Returns true if this member is a team member of the given blog + * + * @param integer $blogid ID of target weblog + * @return boolean whether to join the weblog or not + * + */ + public function isTeamMember($blogid) + { + $query = 'SELECT * FROM '.sql_table('team').' WHERE' + . ' tblog=' . intval($blogid) + . ' and tmember='. $this->getID(); + $res = DB::getResult($query); + return ($res->rowCount() != 0); + } + + /** + * Member::canAddItem() + * + * @param integer $catid ID of target category + * @return boolean whether to be able to add items to the category or not + * + */ + public function canAddItem($catid) + { + global $manager; + + // if this is a 'newcat' style newcat + // no blog admin of destination blog -> NOK + // blog admin of destination blog -> OK + if ( i18n::strpos($catid,'newcat') === 0 ) + { + // get blogid + list($blogid) = sscanf($catid,"newcat-%d"); + return $this->blogAdminRights($blogid); + } + + // category does not exist -> NOK + if ( !$manager->existsCategory($catid) ) + { + return 0; + } + + $blogid = getBlogIDFromCatID($catid); + + // no team rights for blog -> NOK + if (!$this->teamRights($blogid)) + { + return 0; + } + + // all other cases: OK + return 1; + } + + /** + * Member::canAlterComment() + * Returns true if this member can edit/delete a commentitem. This can be in the + * following cases: + * - member is a super-admin + * - member is the author of the comment + * - member is admin of the blog associated with the comment + * - member is author of the item associated with the comment + * + * @param integer $commentid ID of target comment + * @return boolean delete/edit the comment or not + * + */ + public function canAlterComment($commentid) + { + if ( $this->isAdmin() ) + { + return 1; + } + + $query = 'SELECT citem as itemid, iblog as blogid, cmember as cauthor, iauthor' + . ' FROM '.sql_table('comment') .', '.sql_table('item').', '.sql_table('blog') + . ' WHERE citem=inumber and iblog=bnumber and cnumber=' . intval($commentid); + $res = DB::getRow($query); + + return ($res['cauthor'] == $this->getID()) or $this->isBlogAdmin($res['blogid']) or ($res['iauthor'] == $this->getID()); + } + + /** + * Member::canAlterItem() + * Returns true if this member can edit/delete an item. This is true in the following + * cases: - member is a super-admin + * - member is the author of the item + * - member is admin of the the associated blog + * + * @param integer $itemid ID of target item + * @return boolean delete/edit the item or not + * + */ + public function canAlterItem($itemid) + { + if ($this->isAdmin()) return 1; + + $query = 'SELECT iblog, iauthor FROM '.sql_table('item').' WHERE inumber=' . intval($itemid); + $res = DB::getRow($query); + return ($res['iauthor'] == $this->getID()) or $this->isBlogAdmin($res['iblog']); + } + + /** + * Member::canBeDeleted() + * Return true if member can be deleted. This means that there are no items posted by the member left + * + * @param void + * @return boolean whether there is no items or exists + * + */ + public function canBeDeleted() + { + $res = DB::getResult('SELECT * FROM '.sql_table('item').' WHERE iauthor=' . $this->getID()); + return ( $res->rowCount() == 0 ); + } + + /** + * Member::canUpdateItem() + * returns true if this member can move/update an item to a given category, + * false if not (see comments fot the tests that are executed) + * + * @param integer $itemid + * @param string $newcat (can also be of form 'newcat-x' with x=blogid) + * @return boolean whether being able to update the item or not + * + */ + public function canUpdateItem($itemid, $newcat) + { + global $manager; + + // item does not exists -> NOK + if ( !$manager->existsItem($itemid,1,1) ) + { + return 0; + } + + // cannot alter item -> NOK + if (!$this->canAlterItem($itemid)) + { + return 0; + } + + // if this is a 'newcat' style newcat + // no blog admin of destination blog -> NOK + // blog admin of destination blog -> OK + if ( i18n::strpos($newcat, 'newcat') === 0 ) + { + // get blogid + list($blogid) = sscanf($newcat, 'newcat-%d'); + return $this->blogAdminRights($blogid); + } + + // category does not exist -> NOK + if (!$manager->existsCategory($newcat)) + { + return 0; + } + + // get item + $item =& $manager->getItem($itemid,1,1); + + // old catid = new catid -> OK + if ($item['catid'] == $newcat) + { + return 1; + } + + // not a valid category -> NOK + $validCat = DB::getValue('SELECT COUNT(*) AS result FROM '.sql_table('category').' WHERE catid='.intval($newcat)); + if ( !$validCat ) + { + return 0; + } + + // get destination blog + $item =& $manager->getItem($itemid, 1, 1); + $source_blogid = $item['blogid']; + $dest_blogid = getBlogIDFromCatID($newcat); + + // not a team member of destination blog -> NOK + if ( !$this->teamRights($dest_blogid) ) + { + return 0; + } + + // if member is author of item -> OK + if ( $item['authorid'] == $this->getID() ) + { + return 1; + } + + // if member has admin rights on both blogs: OK + if ( ($this->blogAdminRights($dest_blogid)) && ($this->blogAdminRights($source_blogid)) ) + { + return 1; + } + + // all other cases: NOK + return 0; + } + + /** + * Member::setCookies() + * Sets the cookies for the member + * + * @param boolean $shared set this to 1 when using a shared computer. Cookies will expire + * at the end of the session in this case. + * @return void + * + */ + public function setCookies($shared = 0) + { + global $CONF; + + if ( $CONF['SessionCookie'] || $shared ) + { + $lifetime = 0; + } + else + { + $lifetime = time()+2592000; + } + + setcookie($CONF['CookiePrefix'] . 'user', $this->getDisplayName(), $lifetime, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + setcookie($CONF['CookiePrefix'] . 'loginkey', $this->getCookieKey(), $lifetime, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + + // make sure cookies on shared pcs don't get renewed + if ( $shared ) + { + setcookie($CONF['CookiePrefix'] .'sharedpc', '1',$lifetime,$CONF['CookiePath'],$CONF['CookieDomain'],$CONF['CookieSecure']); + } + return; + } + + /** + * Member::sendActivationLink() + * Send activation mail + * + * @param string $type activation type + * @param string $extra extra info + * @return void + */ + public function sendActivationLink($type, $extra='') + { + global $CONF; + + if ( !isset($CONF['ActivationDays']) ) + { + $CONF['ActivationDays'] = 2; + } + + // generate key and URL + $key = $this->generateActivationEntry($type, $extra); + $url = $CONF['AdminURL'] . 'index.php?action=activate&key=' . $key; + + // choose text to use in mail + switch ( $type ) + { + case 'register': + $message = _ACTIVATE_REGISTER_MAIL; + $subject = _ACTIVATE_REGISTER_MAILTITLE; + break; + case 'forgot': + $message = _ACTIVATE_FORGOT_MAIL; + $subject = _ACTIVATE_FORGOT_MAILTITLE; + break; + case 'addresschange': + $message = _ACTIVATE_CHANGE_MAIL; + $subject = _ACTIVATE_CHANGE_MAILTITLE; + break; + default; + } + + // fill out variables in text + $aVars = array( + 'siteName' => $CONF['SiteName'], + 'siteUrl' => $CONF['IndexURL'], + 'memberName' => $this->getDisplayName(), + 'activationUrl' => $url, + 'activationDays' => $CONF['ActivationDays'] + ); + + $message = Template::fill($message, $aVars); + $subject = Template::fill($subject, $aVars); + + // send mail + NOTIFICATION::mail($this->getEmail(), $subject ,$message, $CONF['AdminEmail'], i18n::get_current_charset()); + + ActionLog::add(INFO, _ACTIONLOG_ACTIVATIONLINK . ' (' . $this->getDisplayName() . ' / type: ' . $type . ')'); + return; + } + + /** + * Member::getAdminBlogs() + * Returns an array of all blogids for which member has admin rights + * + * @param void + * @return array weblog IDs in which this member has admin rights + * + */ + public function getAdminBlogs() + { + $blogs = array(); + + if ($this->isAdmin()) + { + $query = 'SELECT bnumber as blogid from '.sql_table('blog'); + } + else + { + $query = 'SELECT tblog as blogid from '.sql_table('team').' where tadmin=1 and tmember=' . $this->getID(); + } + + $res = DB::getResult($query); + if ( $res->rowCount() > 0 ) + { + foreach ( $res as $row ) + { + array_push($blogs, $row['blogid']); + } + } + return $blogs; + } + + /** + * Member::getTeamBlogs() + * Returns an array of all blogids for which member has team rights + * + * @param boolean $incAdmin whether checking weblog admin rights or not + * @return array weblog IDs in which this member join + * + */ + public function getTeamBlogs($incAdmin = 1) + { + $incAdmin = intval($incAdmin); + $blogs = array(); + + if ( $this->isAdmin() && $incAdmin ) + { + $query = 'SELECT bnumber as blogid from '.sql_table('blog'); + } + else + { + $query = 'SELECT tblog as blogid from '.sql_table('team').' where tmember=' . $this->getID(); + } + + $res = DB::getResult($query); + if ( $res->rowCount() > 0 ) + { + foreach ( $res as $row ) + { + array_push($blogs, $row['blogid']); + } + } + return $blogs; + } + + /** + * Member::getNotifyFromMailAddress() + * + * Returns an email address from which notification of commenting/karma voting can + * be sent. A suggestion can be given for when the member is not logged in + * + * @param String $suggest + * @return String mail address or suggestion + */ + public function getNotifyFromMailAddress($suggest = "") + { + global $CONF; + if ( $this->isLoggedIn() ) + { + return $this->getDisplayName() . " <" . $this->getEmail() . ">"; + } + else if ( NOTIFICATION::address_validation($suggest) ) + { + return $suggest; + } + return $CONF['AdminEmail']; + } + + /** + * Member::write() + * Write data to database + * + * @param void + * @return void + * + */ + public function write() + { + $query = 'UPDATE '.sql_table('member') + . ' SET mname=' . DB::quoteValue($this->displayname) . ', ' + . 'mrealname='. DB::quoteValue($this->realname) . ', ' + . 'mpassword='. DB::quoteValue($this->password) . ', ' + . 'mcookiekey='. DB::quoteValue($this->cookiekey) . ', ' + . 'murl=' . DB::quoteValue($this->url) . ', ' + . 'memail=' . DB::quoteValue($this->email) . ', ' + . 'madmin=' . intval($this->admin) . ', ' + . 'mnotes=' . DB::quoteValue($this->notes) . ', ' + . 'mcanlogin=' . intval($this->canlogin) . ', ' + . 'mlocale=' . DB::quoteValue($this->locale) . ', ' + . 'madminskin=' . DB::quoteValue($this->adminskin) . ', ' + . 'mbkmklt=' . DB::quoteValue($this->bookmarklet) . ', ' + . 'mautosave=' . intval($this->autosave) . ' ' + . 'WHERE mnumber=' . intval($this->id); + DB::execute($query); + return; + } + + public function checkCookieKey($key) + { + return ( ($key != '') && ( $key == $this->getCookieKey() ) ); + } + + public function checkPassword($pw) + { + /* for lower compatibility (md5) */ + if ( strlen($this->password) === 32 ) + { + return (md5($pw) == $this->password); + } + return ($this->hash($pw) == $this->password); + } + + public function getRealName() + { + return $this->realname; + } + + public function setRealName($name) + { + $this->realname = $name; + } + + public function getEmail() + { + return $this->email; + } + + public function setEmail($email) + { + $this->email = $email; + } + + public function getPassword() + { + return $this->password; + } + + public function setPassword($pwd) + { + $this->password = $this->hash($pwd); + } + + public function getCookieKey() + { + return $this->cookiekey; + } + + /** + * Member::newCookieKey() + * Generate new cookiekey, save it, and return it + * + * @param void + * @return void + * + */ + public function newCookieKey() + { + mt_srand( (double) microtime() * 1000000); + $this->cookiekey = $this->hash(uniqid(mt_rand())); + $this->write(); + return $this->cookiekey; + } + + public function setCookieKey($val) + { + $this->cookiekey = $val; + } + + public function getURL() + { + return $this->url; + } + + public function setURL($site) + { + $this->url = $site; + } + + public function setAdminSkin($skin) + { + $this->adminskin = $skin; + } + + public function setBookmarklet($skin) + { + $this->bookmarklet = $skin; + } + + public function getAdminSkin() + { + return $this->adminskin; + } + + public function getBookmarklet() + { + return $this->bookmarklet; + } + + public function getLocale() + { + return $this->locale; + } + + public function setLocale($locale) + { + if ( !preg_match('#^(.+)_(.+)_(.+)$#', $locale) + && ($locale = i18n::convert_old_language_file_name_to_locale($locale)) === FALSE ) + { + $locale = ''; + } + $this->locale = $locale; + return; + } + + public function setDisplayName($nick) + { + $this->displayname = $nick; + } + + public function getDisplayName() + { + return $this->displayname; + } + + public function isAdmin() + { + return $this->admin; + } + + public function setAdmin($val) + { + $this->admin = $val; + } + + public function canLogin() + { + return $this->canlogin; + } + + public function setCanLogin($val) + { + $this->canlogin = $val; + } + + public function getNotes() + { + return $this->notes; + } + + public function setNotes($val) + { + $this->notes = $val; + } + + public function getAutosave() + { + return $this->autosave; + } + + public function setAutosave($val) + { + $this->autosave = $val; + return; + } + + /** + * Member::getID() + * + * @param void + * @return integer id of this member object + * + */ + public function getID() + { + return $this->id; + } + + /** + * Member::exists() + * Returns true if there is a member with the given login name + * + * @static + * @param string $name target name + * @return boolean whether target name exists or not + */ + public static function exists($name) + { + $r = DB::getResult('SELECT * FROM ' . sql_table('member') . ' WHERE mname=' . DB::quoteValue($name)); + return ( $r->rowCount() != 0 ); + } + + /** + * Member::existsID() + * Returns true if there is a member with the given ID + * + * @static + * @param integer $id target id + * @return boolean whether target id exists or not + * + */ + public static function existsID($id) + { + $r = DB::getResult('SELECT * FROM ' . sql_table('member') . ' WHERE mnumber=' . intval($id)); + return ( $r->rowCount() != 0 ); + } + + /** + * Member::isNameProtected() + * Checks if a username is protected. + * If so, it can not be used on anonymous comments + * + * @param string $name target name + * @return boolean whether the name exists or not + * + */ + public function isNameProtected($name) + { + // extract name + $name = strip_tags($name); + $name = trim($name); + return self::exists($name); + } + + /** + * Member::create() + * Adds a new member + * + * @static + * @param String $name + * @param String $realname + * @param String $password + * @param String $email + * @param String $url + * @param String $admin + * @param String $canlogin + * @param String $notes + * @return String 1 if success, others if fail + */ + static public function create($name, $realname, $password, $email, $url, $admin, $canlogin, $notes) + { + if ( !NOTIFICATION::address_validation($email) ) + { + return _ERROR_BADMAILADDRESS; + } + + /* TODO: this method should be in MEMBER class, not globalfunctions */ + if ( !isValidDisplayName($name) ) + { + return _ERROR_BADNAME; + } + + if ( self::exists($name) ) + { + return _ERROR_NICKNAMEINUSE; + } + + if ( !$realname ) + { + return _ERROR_REALNAMEMISSING; + } + + /* TODO: check the number of characters */ + if ( !$password ) + { + return _ERROR_PASSWORDMISSING; + } + + /* + * begin if: sometimes user didn't prefix the URL with http:// or https://, + * this cause a malformed URL. Let's fix it. + */ + + if ( !preg_match('#^https?://#', $url) ) + { + $url = 'http://' . $url; + } + + $name = DB::quoteValue($name); + $realname = DB::quoteValue($realname); + /* NOTE: hashed password is automatically updated if the length is 32 bytes when logging in */ + $password = DB::quoteValue(md5($password)); + $email = DB::quoteValue($email); + $url = DB::quoteValue($url); + $admin = (integer) $admin; + $canlogin = (integer) $canlogin; + $notes = DB::quoteValue($notes); + + $query = "INSERT INTO %s" + . " (MNAME,MREALNAME,MPASSWORD,MEMAIL,MURL, MADMIN, MCANLOGIN, MNOTES)" + . " VALUES (%s, %s, %s, %s, %s, %d, %d, %s)"; + $query = sprintf($query, sql_table('member'), $name, $realname, $password, $email, $url, $admin, $canlogin, $notes); + DB::execute($query); + + ActionLog::add(INFO, _ACTIONLOG_NEWMEMBER . ' ' . $name); + + return 1; + } + + /** + * Member::getActivationInfo() + * Returns activation info for a certain key (an object with properties vkey, vmember, ...) + * + * @static + * @param string $key activation key + * @return mixed return 0 if failed, else return activation table object + * + */ + public static function getActivationInfo($key) + { + $query = 'SELECT * FROM ' . sql_table('activation') . ' WHERE vkey=' . DB::quoteValue($key); + $res = DB::getResult($query); + + if ( !$res || ($res->rowCount() == 0) ) + { + return 0; + } + return $res->fetch(); + } + + /** + * Member::generateActivationEntry() + * Creates an account activation key + * addresschange -> old email address + * + * @param string $type one of the following values (determines what to do when activation expires) + * 'register' (new member registration) + * 'forgot' (forgotton password) + * 'addresschange' (member address has changed) + * @param string $extra extra info (needed when validation link expires) + * @return string activation key + */ + public function generateActivationEntry($type, $extra = '') + { + // clean up old entries + $this->cleanupActivationTable(); + + // kill any existing entries for the current member (delete is ok) + // (only one outstanding activation key can be present for a member) + DB::execute('DELETE FROM ' . sql_table('activation') . ' WHERE vmember=' . intval($this->getID())); + + // indicates if the member can log in while the link is active + $canLoginWhileActive = false; + switch ( $type ) + { + case 'forgot': + $canLoginWhileActive = true; + break; + case 'register': + break; + case 'addresschange': + $extra = $extra . '/' . ( $this->canLogin() ? '1' : '0' ); + break; + } + + $ok = false; + while ( !$ok ) + { + // generate a random key + srand((double)microtime()*1000000); + $key = $this->hash(uniqid(rand(), true)); + + // attempt to add entry in database + // add in database as non-active + $query = 'INSERT INTO %s (vkey, vtime, vmember, vtype, vextra) VALUES (%s, %s, %d, %s, %s)'; + $query = sprintf($query + , sql_table('activation') + , DB::quoteValue($key) + , DB::formatDateTime() + , intval($this->getID()) + , DB::quoteValue($type) + , DB::quoteValue($extra) + ); + if ( DB::execute($query) !== FALSE ) + $ok = true; + } + + // mark member as not allowed to log in + if ( !$canLoginWhileActive ) + { + $this->setCanLogin(0); + $this->write(); + } + + // return the key + return $key; + } + + /** + * Member::activate() + * Inidicates that an activation link has been clicked and any forms displayed + * there have been successfully filled out. + * + * @param string $key activation key + * @return boolean + * + */ + public function activate($key) + { + // get activate info + $info = self::getActivationInfo($key); + + // no active key + if ( !$info ) + { + return false; + } + + switch ( $info['vtype'] ) + { + case 'forgot': + // nothing to do + break; + case 'register': + // set canlogin value + global $CONF; + DB::execute('UPDATE ' . sql_table('member') . ' SET mcanlogin=' . intval($CONF['NewMemberCanLogon']). ' WHERE mnumber=' . intval($info['vmember'])); + break; + case 'addresschange': + // reset old 'canlogin' value + list($oldEmail, $oldCanLogin) = preg_split('#/#', $info['vextra']); + DB::execute('UPDATE ' . sql_table('member') . ' SET mcanlogin=' . intval($oldCanLogin). ' WHERE mnumber=' . intval($info['vmember'])); + break; + } + + // delete from activation table + DB::execute('DELETE FROM ' . sql_table('activation') . ' WHERE vkey=' . DB::quoteValue($key)); + + // success! + return true; + } + + /** + * Member::cleanupActivationTable() + * Cleans up entries in the activation table. All entries older than 2 days are removed. + * (static) + * + * @param void + * @return void + */ + public function cleanupActivationTable() + { + $actdays = 2; + if ( isset($CONF['ActivationDays']) && intval($CONF['ActivationDays']) > 0 ) + { + $actdays = intval($CONF['ActivationDays']); + } + else + { + $CONF['ActivationDays'] = 2; + } + $boundary = time() - (60 * 60 * 24 * $actdays); + + // 1. walk over all entries, and see if special actions need to be performed + $query = sprintf('SELECT * FROM %s WHERE vtime < %s', sql_table('activation'), DB::formatDateTime($boundary)); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + switch ( $row['vtype'] ) + { + case 'register': + // delete all information about this site member. registration is undone because there was + // no timely activation + include_once($DIR_LIBS . 'ADMIN.php'); + Admin::deleteOneMember(intval($row['vmember'])); + break; + case 'addresschange': + // revert the e-mail address of the member back to old address + list($oldEmail, $oldCanLogin) = preg_split('#/#', $row['vextra']); + DB::execute('UPDATE ' . sql_table('member') . ' SET mcanlogin=' . intval($oldCanLogin). ', memail=' . DB::quoteValue($oldEmail). ' WHERE mnumber=' . intval($row['vmember'])); + break; + case 'forgot': + // delete the activation link and ignore. member can request a new password using the + // forgot password link + break; + } + } + + // 2. delete activation entries for real + $query = sprintf('DELETE FROM %s WHERE vtime < %s', sql_table('activation'), DB::formatDateTime($boundary)); + DB::execute($query); + return; + } + + /** + * Member::$language + * + * @obsolete + * @param void + * @return void + * + */ + public $language = ''; + /** + * Member::getLanguage() + * + * @obsolete + * @param void + * @return void + * + */ + public function getLanguage() + { + if ( ($language = i18n::convert_locale_to_old_language_file_name($this->locale)) === FALSE ) + { + $language = ''; + } + return $language; + } + } ++>>>>>>> skinnable-master diff --combined nucleus/libs/NOTIFICATION.php index 22fe7e1,1d708d1..e7f3d38 --- a/nucleus/libs/NOTIFICATION.php +++ b/nucleus/libs/NOTIFICATION.php @@@ -1,399 -1,399 +1,801 @@@ ++<<<<<<< HEAD +$#", $mailbox, $match) ) + { + $display_name = self::seven_bit_characters_encoder(trim($match[1])); + $local_part = trim($match[2]); + $domain = trim($match[3]); + $encoded_mailboxes[] = "{$display_name} <{$local_part}@{$domain}>"; + } + else if ( preg_match("#([^,]+)?@([^,]+)?#", $mailbox) ) + { + $encoded_mailboxes[] = $mailbox; + } + else + { + continue; + } + } + if ( $encoded_mailboxes == array() ) + { + return FALSE; + } + return implode(',', $encoded_mailboxes); + } + + /** + * NOTIFICATION::seven_bit_characters_encoder + * Encoder into 7bit ASCII expression for Non-ASCII Text based on RFC 2047. + * + * @link http://www.ietf.org/rfc/rfc2047.txt + * @see 2. Syntax of encoded-words + * + * NOTE: RFC 2047 has a ambiguousity for dealing with 'linear-white-space'. + * This causes a trouble related to line breaking between single byte and multi-byte strings. + * To avoid this, single byte string is encoded as well as multi byte string here. + * + * NOTE: RFC 2231 also defines the way to use non-ASCII characters in MIME header. + * http://www.ietf.org/rfc/rfc2231.txt + * + * NOTE: iconv extension give the same functions as this in PHP5 + * iconv_mime_encode(): + * http://www.php.net/manual/en/function.iconv-mime-encode.php + * + * @static + * @param string $charset Character set encoding + * @param string $type type of 7 bit encoding, should be 'B' or 'Q' + * @param string $string Target string with header field + * @return string encoded string + * + */ + static private function seven_bit_characters_encoder($string) + { + $header = chr(13) . chr(10) . chr(32) . '=?' . self::$charset . '?' . self::$scheme . '?'; + $footer = "?="; + $restriction = 78 - strlen($header) - strlen($footer) ; + + $encoded_words = array(); + for ( $i = 0; $i < i18n::strlen($string); $i++ ) + { + if ( self::$scheme == 'B' ) + { + if ( $i == 0 ) + { + $letters = ''; + } + + $letter = i18n::substr($string, $i, 1); + $expected_length = strlen($letters) + strlen($letter) * 4 / 3; + + if ( $expected_length > $restriction ) + { + $encoded_text = self::b_encoder($letters); + $encoded_words[] = "{$header}{$encoded_text}{$footer}"; + $letters = ''; + } + + $letters .= $letter; + + if ( $i == i18n::strlen($string) - 1 ) + { + $encoded_text = self::b_encoder($letters); + $encoded_words[] = "{$header}{$encoded_text}{$footer}"; + break; + } + continue; + } + else + { + if ( $i == 0 ) + { + $encoded_text = ''; + } + + $encoded_letter = self::q_encoder(i18n::substr($string, $i, 1)); + $expected_length = strlen($encoded_text) + strlen($encoded_letter); + + if ( $expected_length > $restriction ) + { + $encoded_words[] = "{$header}{$encoded_text}{$footer}"; + $letters = ''; + } + + $encoded_text .= $encoded_letter; + + if ( $i == i18n::strlen($string) - 1 ) + { + $encoded_words[] = "{$header}{$encoded_text}{$footer}"; + break; + } + continue; + } + } + + return implode('', $encoded_words); + } + + /** + * NOTIFICATION::b_encoder() + * + * B encoder according to RFC 2047. + * The "B" encoding is identical to the "BASE64" encoding defined by RFC 4648. + * + * @link http://www.ietf.org/rfc/rfc4648.txt + * @see 6.8. Base64 Content-Transfer-Encoding + * + * NOTE: According to RFC 4648 + * (1) The final quantum of encoding input is an integral multiple of 24 bits; + * here, the final unit of encoded output will be an integral multiple + * of 4 characters with no "=" padding. + * (2) The final quantum of encoding input is exactly 8 bits; here, + * the final unit of encoded output will be two characters followed + * by two "=" padding characters. + * (3) The final quantum of encoding input is exactly 16 bits; here, + * the final unit of encoded output will be three characters followed + * by one "=" padding character. + * + * @static + * @param string $target targetted string + * @return string encoded string + */ + static private function b_encoder($target) + { + return base64_encode($target); + } + + /** + * NOTIFICATION::q_encoder() + * + * Q encoder according to RFC 2047. + * The "Q" encoding is similar to "Quoted-Printable" content-transfer-encoding defined in RFC 2045, + * but the "Q" encoding and the "Quoted-Printable" are different a bit. + * + * @link http://www.ietf.org/rfc/rfc2047.txt + * @see 4.2. The "Q" encoding + * + * NOTE: According to RFC 2047 + * (1) Any 8-bit value may be represented by a "=" followed by two hexadecimal digits. + * For example, if the character set in use were ISO-8859-1, + * the "=" character would thus be encoded as "=3D", and a SPACE by "=20". + * (Upper case should be used for hexadecimal digits "A" through "F".) + * (2) The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be + * represented as "_" (underscore, ASCII 95.). + * (This character may not pass through some internetwork mail gateways, + * but its use will greatly enhance readability of "Q" encoded data + * with mail readers that do not support this encoding.) + * Note that the "_" always represents hexadecimal 20, + * even if the SPACE character occupies a different code position + * in the character set in use. + * (3) 8-bit values which correspond to printable ASCII characters + * other than "=", "?", and "_" (underscore), MAY be represented as those characters. + * (But see section 5 for restrictions.) + * In particular, SPACE and TAB MUST NOT be represented as themselves within encoded words. + * + * @static + * @param string $target targetted string + * @return string encoded string + */ + static private function q_encoder($target) + { + $string = ''; + + for ( $i = 0; $i < strlen($target); $i++ ) + { + $letter = substr ($target, $i, 1); + $order = ord($letter); + + // Printable ASCII characters without "=", "?", "_" + if ((33 <= $order && $order <= 60) + || (62 == $order) + || (64 <= $order && $order <= 94) + || (96 <= $order && $order <= 126)) + { + $string .= strtoupper(dechex($order)); + } + // Space shuold be encoded as the same strings as "_" + else if ($order == 32) + { + $string .= '_'; + } + // Other characters + else + { + $string .= '=' . strtoupper(dechex($order)); + } + } + + return $string; + } + + /** + * NOTICE: Deprecated + * NOTIFICATION::$addresses + * + * @deprecated + */ + private $addresses = array(); + + /** + * NOTICE: Deprecated + * takes one string as argument, containing multiple e-mail addresses + * separated by semicolons + * eg: site@demuynck.org;nucleus@demuynck.org;foo@bar.com + * + * @deprecated + */ + function __construct($addresses) + { + $this->addresses = preg_split('#;#' , $addresses); + } + + /** + * NOTICE: Deprecated + * NOTIFICATION::validAddresses() + * + * returns true if all addresses are valid + * + * @deprecated + * @param Void + * @return Boolean + */ + function validAddresses() + { + foreach ( $this->addresses as $address ) + { + if ( !self::address_validation(trim($address)) ) + { + return 0; + } + } + return 1; + } + + /** + * NOTICE: Deprecated + * NOTIFICATION::notify() + * + * Sends email messages to all the email addresses + * + * @deprecated + * @param String $title + * @param String $message + * @param String $from + * @return Void + */ + function notify($title, $message, $from) + { + global $member; + $addresses = array(); + + foreach ($this->addresses as $address) + { + if ( $member->isLoggedIn() && ($member->getEmail() == $address) ) + { + continue; + } + $addresses[] = $address; + } + + self::mail(implode(',', $addresses), $title, $message , $from); + return; + } +} ++======= + $#", $mailbox, $match) ) + { + $display_name = self::seven_bit_characters_encoder(trim($match[1])); + $local_part = trim($match[2]); + $domain = trim($match[3]); + $encoded_mailboxes[] = "{$display_name} <{$local_part}@{$domain}>"; + } + else if ( preg_match("#([^,]+)?@([^,]+)?#", $mailbox) ) + { + $encoded_mailboxes[] = $mailbox; + } + else + { + continue; + } + } + if ( $encoded_mailboxes == array() ) + { + return FALSE; + } + return implode(',', $encoded_mailboxes); + } + + /** + * NOTIFICATION::seven_bit_characters_encoder + * Encoder into 7bit ASCII expression for Non-ASCII Text based on RFC 2047. + * + * @link http://www.ietf.org/rfc/rfc2047.txt + * @see 2. Syntax of encoded-words + * + * NOTE: RFC 2047 has a ambiguousity for dealing with 'linear-white-space'. + * This causes a trouble related to line breaking between single byte and multi-byte strings. + * To avoid this, single byte string is encoded as well as multi byte string here. + * + * NOTE: RFC 2231 also defines the way to use non-ASCII characters in MIME header. + * http://www.ietf.org/rfc/rfc2231.txt + * + * NOTE: iconv extension give the same functions as this in PHP5 + * iconv_mime_encode(): + * http://www.php.net/manual/en/function.iconv-mime-encode.php + * + * @static + * @param string $charset Character set encoding + * @param string $type type of 7 bit encoding, should be 'B' or 'Q' + * @param string $string Target string with header field + * @return string encoded string + * + */ + static private function seven_bit_characters_encoder($string) + { + $header = chr(13) . chr(10) . chr(32) . '=?' . self::$charset . '?' . self::$scheme . '?'; + $footer = "?="; + $restriction = 78 - strlen($header) - strlen($footer) ; + + $encoded_words = array(); + for ( $i = 0; $i < i18n::strlen($string); $i++ ) + { + if ( self::$scheme == 'B' ) + { + if ( $i == 0 ) + { + $letters = ''; + } + + $letter = i18n::substr($string, $i, 1); + $expected_length = strlen($letters) + strlen($letter) * 4 / 3; + + if ( $expected_length > $restriction ) + { + $encoded_text = self::b_encoder($letters); + $encoded_words[] = "{$header}{$encoded_text}{$footer}"; + $letters = ''; + } + + $letters .= $letter; + + if ( $i == i18n::strlen($string) - 1 ) + { + $encoded_text = self::b_encoder($letters); + $encoded_words[] = "{$header}{$encoded_text}{$footer}"; + break; + } + continue; + } + else + { + if ( $i == 0 ) + { + $encoded_text = ''; + } + + $encoded_letter = self::q_encoder(i18n::substr($string, $i, 1)); + $expected_length = strlen($encoded_text) + strlen($encoded_letter); + + if ( $expected_length > $restriction ) + { + $encoded_words[] = "{$header}{$encoded_text}{$footer}"; + $letters = ''; + } + + $encoded_text .= $encoded_letter; + + if ( $i == i18n::strlen($string) - 1 ) + { + $encoded_words[] = "{$header}{$encoded_text}{$footer}"; + break; + } + continue; + } + } + + return implode('', $encoded_words); + } + + /** + * NOTIFICATION::b_encoder() + * + * B encoder according to RFC 2047. + * The "B" encoding is identical to the "BASE64" encoding defined by RFC 4648. + * + * @link http://www.ietf.org/rfc/rfc4648.txt + * @see 6.8. Base64 Content-Transfer-Encoding + * + * NOTE: According to RFC 4648 + * (1) The final quantum of encoding input is an integral multiple of 24 bits; + * here, the final unit of encoded output will be an integral multiple + * of 4 characters with no "=" padding. + * (2) The final quantum of encoding input is exactly 8 bits; here, + * the final unit of encoded output will be two characters followed + * by two "=" padding characters. + * (3) The final quantum of encoding input is exactly 16 bits; here, + * the final unit of encoded output will be three characters followed + * by one "=" padding character. + * + * @static + * @param string $target targetted string + * @return string encoded string + */ + static private function b_encoder($target) + { + return base64_encode($target); + } + + /** + * NOTIFICATION::q_encoder() + * + * Q encoder according to RFC 2047. + * The "Q" encoding is similar to "Quoted-Printable" content-transfer-encoding defined in RFC 2045, + * but the "Q" encoding and the "Quoted-Printable" are different a bit. + * + * @link http://www.ietf.org/rfc/rfc2047.txt + * @see 4.2. The "Q" encoding + * + * NOTE: According to RFC 2047 + * (1) Any 8-bit value may be represented by a "=" followed by two hexadecimal digits. + * For example, if the character set in use were ISO-8859-1, + * the "=" character would thus be encoded as "=3D", and a SPACE by "=20". + * (Upper case should be used for hexadecimal digits "A" through "F".) + * (2) The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be + * represented as "_" (underscore, ASCII 95.). + * (This character may not pass through some internetwork mail gateways, + * but its use will greatly enhance readability of "Q" encoded data + * with mail readers that do not support this encoding.) + * Note that the "_" always represents hexadecimal 20, + * even if the SPACE character occupies a different code position + * in the character set in use. + * (3) 8-bit values which correspond to printable ASCII characters + * other than "=", "?", and "_" (underscore), MAY be represented as those characters. + * (But see section 5 for restrictions.) + * In particular, SPACE and TAB MUST NOT be represented as themselves within encoded words. + * + * @static + * @param string $target targetted string + * @return string encoded string + */ + static private function q_encoder($target) + { + $string = ''; + + for ( $i = 0; $i < strlen($target); $i++ ) + { + $letter = substr ($target, $i, 1); + $order = ord($letter); + + // Printable ASCII characters without "=", "?", "_" + if ((33 <= $order && $order <= 60) + || (62 == $order) + || (64 <= $order && $order <= 94) + || (96 <= $order && $order <= 126)) + { + $string .= strtoupper(dechex($order)); + } + // Space shuold be encoded as the same strings as "_" + else if ($order == 32) + { + $string .= '_'; + } + // Other characters + else + { + $string .= '=' . strtoupper(dechex($order)); + } + } + + return $string; + } + + /** + * NOTICE: Deprecated + * NOTIFICATION::$addresses + * + * @deprecated + */ + private $addresses = array(); + + /** + * NOTICE: Deprecated + * takes one string as argument, containing multiple e-mail addresses + * separated by semicolons + * eg: site@demuynck.org;nucleus@demuynck.org;foo@bar.com + * + * @deprecated + */ + function __construct($addresses) + { + $this->addresses = preg_split('#;#' , $addresses); + } + + /** + * NOTICE: Deprecated + * NOTIFICATION::validAddresses() + * + * returns true if all addresses are valid + * + * @deprecated + * @param Void + * @return Boolean + */ + function validAddresses() + { + foreach ( $this->addresses as $address ) + { + if ( !self::address_validation(trim($address)) ) + { + return 0; + } + } + return 1; + } + + /** + * NOTICE: Deprecated + * NOTIFICATION::notify() + * + * Sends email messages to all the email addresses + * + * @deprecated + * @param String $title + * @param String $message + * @param String $from + * @return Void + */ + function notify($title, $message, $from) + { + global $member; + $addresses = array(); + + foreach ($this->addresses as $address) + { + if ( $member->isLoggedIn() && ($member->getEmail() == $address) ) + { + continue; + } + $addresses[] = $address; + } + + self::mail(implode(',', $addresses), $title, $message , $from); + return; + } + } ++>>>>>>> skinnable-master diff --combined nucleus/libs/PARSER.php index c23d297,406fe8c..79f372e --- a/nucleus/libs/PARSER.php +++ b/nucleus/libs/PARSER.php @@@ -12,7 -12,7 +12,11 @@@ /** * @license http://nucleuscms.org/license.txt GNU General Public License * @copyright Copyright (C) 2002-2009 The Nucleus Group ++<<<<<<< HEAD + * @version $Id: PARSER.php 1757 2012-04-15 09:02:32Z sakamocchi $ ++======= + * @version $Id: PARSER.php 1879 2012-06-17 07:45:09Z sakamocchi $ ++>>>>>>> skinnable-master */ if ( !function_exists('requestVar') ) @@@ -62,8 -62,6 +66,11 @@@ class Parse $this->pdelim = $pdelim; $this->norestrictions = 0; // set this to 1 to disable checking for allowedActions ++<<<<<<< HEAD + $this->skin = NULL; + ++======= ++>>>>>>> skinnable-master $handler->setParser($this); return; @@@ -137,7 -135,7 +144,11 @@@ if ( in_array($actionlc, $this->actions) || $this->norestrictions ) { ++<<<<<<< HEAD + call_user_func_array(array(&$this->handler, "parse_{$actionlc}"), $params); ++======= + call_user_func_array(array($this->handler, "parse_{$actionlc}"), $params); ++>>>>>>> skinnable-master } else { diff --combined nucleus/libs/PLUGIN.php index 5a175c2,4cebb26..b52b93c --- a/nucleus/libs/PLUGIN.php +++ b/nucleus/libs/PLUGIN.php @@@ -1,984 -1,984 +1,1971 @@@ ++<<<<<<< HEAD + if the plugin uses the sql_table() method to get table names + * 'HelpPage' -> if the plugin provides a helppage + * 'SqlApi' -> if the plugin uses the complete sql_* or DB::* api (must also require nucleuscms 3.5) + */ + public function supportsFeature($feature) + { + return 0; + } + + /** + * Report a list of plugin that is required to final public function + * + * @returns an array of names of plugin, an empty array indicates no dependency + */ + public function getPluginDep() + { + return array(); + } + + // these helper final public functions should not be redefined in your plugin + + /** + * Creates a new option for this plugin + * + * @param name + * A string uniquely identifying your option. (max. length is 20 characters) + * @param description + * A description that will show up in the nucleus admin area (max. length: 255 characters) + * @param type + * Either 'text', 'yesno' or 'password' + * This info is used when showing 'edit plugin options' screens + * @param value + * Initial value for the option (max. value length is 128 characters) + */ + final public function createOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('global', $name, $desc, $type, $defValue, $typeExtras); + } + + final public function createBlogOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('blog', $name, $desc, $type, $defValue, $typeExtras); + } + + final public function createMemberOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('member', $name, $desc, $type, $defValue, $typeExtras); + } + + final public function createCategoryOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('category', $name, $desc, $type, $defValue, $typeExtras); + } + + final public function createItemOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('item', $name, $desc, $type, $defValue, $typeExtras); + } + + /** + * Removes the option from the database + * + * Note: Options get erased automatically on plugin uninstall + */ + final public function deleteOption($name) + { + return $this->delete_option('global', $name); + } + + final public function deleteBlogOption($name) + { + return $this->delete_option('blog', $name); + } + + final public function deleteMemberOption($name) + { + return $this->delete_option('member', $name); + } + + final public function deleteCategoryOption($name) + { + return $this->delete_option('category', $name); + } + + final public function deleteItemOption($name) + { + return $this->delete_option('item', $name); + } + + /** + * Sets the value of an option to something new + */ + final public function setOption($name, $value) + { + return $this->set_option('global', 0, $name, $value); + } + + final public function setBlogOption($blogid, $name, $value) + { + return $this->set_option('blog', $blogid, $name, $value); + } + + final public function setMemberOption($memberid, $name, $value) + { + return $this->set_option('member', $memberid, $name, $value); + } + + final public function setCategoryOption($catid, $name, $value) + { + return $this->set_option('category', $catid, $name, $value); + } + + final public function setItemOption($itemid, $name, $value) { + return $this->set_option('item', $itemid, $name, $value); + } + + /** + * Retrieves the current value for an option + */ + final public function getOption($name) + { + // only request the options the very first time. On subsequent requests + // the static collection is used to save SQL queries. + if ( $this->plugin_options == 0 ) + { + $this->plugin_options = array(); + + $query = "SELECT d.oname as name, o.ovalue as value FROM %s o, %s d WHERE d.opid=%d AND d.oid=o.oid;"; + $query = sprintf($query, sql_table('plugin_option'), sql_table('plugin_option_desc'), (integer) $this->plugid); + $result = DB::getResult($query); + foreach ( $result as $row ) + { + $this->plugin_options[strtolower($row['name'])] = $row['value']; + } + } + if ( isset($this->plugin_options[strtolower($name)]) ) + { + return $this->plugin_options[strtolower($name)]; + } + else + { + return $this->get_option('global', 0, $name); + } + } + + final public function getBlogOption($blogid, $name) + { + return $this->get_option('blog', $blogid, $name); + } + + final public function getMemberOption($memberid, $name) + { + return $this->get_option('member', $memberid, $name); + } + + final public function getCategoryOption($catid, $name) + { + return $this->get_option('category', $catid, $name); + } + + final public function getItemOption($itemid, $name) + { + return $this->get_option('item', $itemid, $name); + } + + /** + * Retrieves an associative array with the option value for each + * context id + */ + final public function getAllBlogOptions($name) + { + return $this->get_all_options('blog', $name); + } + + final public function getAllMemberOptions($name) + { + return $this->get_all_options('member', $name); + } + + final public function getAllCategoryOptions($name) + { + return $this->get_all_options('category', $name); + } + + final public function getAllItemOptions($name) + { + return $this->get_all_options('item', $name); + } + + /** + * Retrieves an indexed array with the top (or bottom) of an option + * (delegates to getOptionTop()) + */ + final public function getBlogOptionTop($name, $amount = 10, $sort = 'desc') + { + return $this->get_option_top('blog', $name, $amount, $sort); + } + + final public function getMemberOptionTop($name, $amount = 10, $sort = 'desc') + { + return $this->get_option_top('member', $name, $amount, $sort); + } + + final public function getCategoryOptionTop($name, $amount = 10, $sort = 'desc') + { + return $this->get_option_top('category', $name, $amount, $sort); + } + + final public function getItemOptionTop($name, $amount = 10, $sort = 'desc') + { + return $this->get_option_top('item', $name, $amount, $sort); + } + + /** + * NucleusPlugin::getID() + * get id for this plugin + * + * @access public + * @param void + * @return integer this plugid id + */ + final public function getID() + { + return (integer) $this->plugid; + } + + /** + * NucleusPlugin::setID() + * set favorite id for this plugin + * + * @access public + * @param integer $plugid favorite id for plugin + * @return void + */ + final public function setID($plugid) + { + $this->plugid = (integer) $plugid; + return; + } + + /** + * Returns the URL of the admin area for this plugin (in case there's + * no such area, the returned information is invalid) + * + * public + */ + final public function getAdminURL() + { + global $CONF; + return $CONF['PluginURL'] . $this->getShortName() . '/'; + } + + /** + * Returns the directory where the admin directory is located and + * where the plugin can maintain his extra files + * + * public + */ + final public function getDirectory() + { + global $DIR_PLUGINS; + return $DIR_PLUGINS . $this->getShortName() . '/'; + } + + /** + * Derives the short name for the plugin from the classname (all + * lowercase) + * + * public + */ + final public function getShortName() + { + return str_replace('np_','',strtolower(get_class($this))); + } + + /** + * Clears the option value cache which saves the option values during + * the plugin execution. This function is usefull if the options has + * changed during the plugin execution (especially in association with + * the PrePluginOptionsUpdate and the PostPluginOptionsUpdate events) + * + * public + **/ + final public function clearOptionValueCache() + { + $this->option_values = array(); + $this->plugin_options = 0; + return; + } + + // internal functions of the class starts here + protected $option_values; // oid_contextid => value + protected $option_info; // context_name => array('oid' => ..., 'default' => ...) + protected $plugin_options; // see getOption() + protected $plugid; // plugin id + + /** + * Class constructor: Initializes some internal data + */ + public function __construct() + { + $this->option_values = array(); // oid_contextid => value + $this->option_info = array(); // context_name => array('oid' => ..., 'default' => ...) + $this->plugin_options = 0; + } + + /** + * Retrieves an array of the top (or bottom) of an option from a plugin. + * @author TeRanEX + * @param string $context the context for the option: item, blog, member,... + * @param string $name the name of the option + * @param int $amount how many rows must be returned + * @param string $sort desc or asc + * @return array array with both values and contextid's + * @access private + */ + final protected function get_option_top($context, $name, $amount = 10, $sort = 'desc') + { + if ( ($sort != 'desc') && ($sort != 'asc') ) + { + $sort= 'desc'; + } + + $oid = $this->get_option_id($context, $name); + + // retrieve the data and return + $query = "SELECT otype, oextra FROM %s WHERE oid = %d;"; + $query = sprintf($query, sql_table('plugin_option_desc'), $oid); + $row = DB::getRow($query); + + if ( ($this->optionCanBeNumeric($row['otype'])) && ($row['oextra'] == 'number' ) ) + { + $orderby = 'CAST(ovalue AS SIGNED)'; + } + else + { + $orderby = 'ovalue'; + } + $query = "SELECT ovalue value, ocontextid id FROM %s WHERE oid = %d ORDER BY %s %s LIMIT 0,%d;"; + $query = sprintf($query, sql_table('plugin_option'), $oid, $orderby, $sort, (integer) $amount); + $result = DB::getResult($query); + + // create the array + $i = 0; + $top = array(); + foreach( $result as $row ) + { + $top[$i++] = $row; + } + + // return the array (duh!) + return $top; + } + + /** + * Creates an option in the database table plugin_option_desc + * + * private + */ + final protected function create_option($context, $name, $desc, $type, $defValue, $typeExtras = '') + { + // create in plugin_option_desc + $query = 'INSERT INTO ' . sql_table('plugin_option_desc') + .' (opid, oname, ocontext, odesc, otype, odef, oextra)' + .' VALUES ('.intval($this->plugid) + .', '.DB::quoteValue($name) + .', '.DB::quoteValue($context) + .', '.DB::quoteValue($desc) + .', '.DB::quoteValue($type) + .', '.DB::quoteValue($defValue) + .', '.DB::quoteValue($typeExtras).')'; + DB::execute($query); + $oid = DB::getInsertId(); + + $key = $context . '_' . $name; + $this->option_info[$key] = array('oid' => $oid, 'default' => $defValue); + return 1; + } + + /** + * Deletes an option from the database tables + * plugin_option and plugin_option_desc + * + * private + */ + final protected function delete_option($context, $name) + { + $oid = $this->get_option_id($context, $name); + if ( !$oid ) + { + return 0; // no such option + } + + // delete all things from plugin_option + $query = "DELETE FROM %s WHERE oid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid); + DB::execute($query); + + // delete entry from plugin_option_desc + $query = "DELETE FROM %s WHERE oid=%d;"; + $query = sprintf($query, sql_table('plugin_option_desc'), $oid); + DB::execute($query); + + // clear from cache + unset($this->option_info["{$context}_{$name}"]); + $this->option_values = array(); + return 1; + } + + /** + * Update an option in the database table plugin_option + * + * returns: 1 on success, 0 on failure + * private + */ + final protected function set_option($context, $contextid, $name, $value) + { + global $manager; + + $oid = $this->get_option_id($context, $name); + if ( !$oid ) + { + return 0; + } + + // check if context id exists + switch ( $context ) + { + case 'member': + if ( !Member::existsID($contextid) ) + { + return 0; + } + break; + case 'blog': + if ( !$manager->existsBlogID($contextid) ) + { + return 0; + } + break; + case 'category': + if ( !$manager->existsCategory($contextid) ) + { + return 0; + } + break; + case 'item': + if ( !$manager->existsItem($contextid, true, true) ) + { + return 0; + } + break; + case 'global': + if ( $contextid != 0 ) + { + return 0; + } + break; + } + + // update plugin_option + $query = "DELETE FROM %s WHERE oid=%d and ocontextid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid); + DB::execute($query); + + $query = "INSERT INTO %s (ovalue, oid, ocontextid) VALUES (%s, %d, %d);"; + $query = sprintf($query, sql_table('plugin_option'), DB::quoteValue($value), $oid, $contextid); + DB::execute($query); + + // update cache + $this->option_values["{$oid}_{$contextid}"] = $value; + if ( $context == 'global' ) + { + $this->plugin_options[strtolower($name)] = $value; + } + + return 1; + } + + /** + * Get an option from Cache or database + * - if not in the option Cache read it from the database + * - if not in the database write default values into the database + * + * private + */ + final protected function get_option($context, $contextid, $name) + { + $oid = $this->get_option_id($context, $name); + if ( !$oid ) + { + return ''; + } + + $key = "{$oid}_{$contextid}"; + + if ( isset($this->option_values[$key]) ) + { + return $this->option_values[$key]; + } + + // get from DB + $query = "SELECT ovalue FROM %s WHERE oid=%d and ocontextid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid); + $result = DB::getResult($query); + + if ( !$result || ($result->rowCount() == 0) ) + { + // fill DB with default value + $this->option_values[$key] = $this->get_default_value($context, $name); + $query = "INSERT INTO %s (oid, ocontextid, ovalue) VALUES (%d, %d, %s);"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid, DB::quoteValue($this->option_values[$key])); + DB::execute($query); + } + else + { + $row = $result->fetch(); + $this->option_values[$key] = $row['ovalue']; + } + + return $this->option_values[$key]; + } + + /** + * Returns assoc array with all values for a given option + * (one option per possible context id) + * + * private + */ + final protected function get_all_options($context, $name) + { + $oid = $this->get_option_id($context, $name); + if ( !$oid ) + { + return array(); + } + $default_value = $this->get_default_value($context, $name); + + $options = array(); + $query = "SELECT %s as contextid FROM %s;"; + switch ( $context ) + { + case 'blog': + $query = sprintf($query, 'bnumber', sql_table('blog')); + break; + case 'category': + $query = sprintf($query, 'catid', sql_table('category')); + break; + case 'member': + $query = sprintf($query, 'mnumber', sql_table('member')); + break; + case 'item': + $query = sprintf($query, 'inumber', sql_table('item')); + break; + } + + $result = DB::getResult($query); + if ( $result ) + { + foreach ( $result as $row ) + { + $options[$row['contextid']] = $default_value; + } + } + + $query = "SELECT ocontextid, ovalue FROM %s WHERE oid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), $oid); + $result = DB::getResult($query); + foreach ( $result as $row ) + { + $options[$row['ocontextid']] = $row['ovalue']; + } + + return $options; + } + + /** + * NucleusPlugin::get_option_id + * + * Gets the 'option identifier' that corresponds to a given option name. + * When this method is called for the first time, all the OIDs for the plugin + * are loaded into memory, to avoid re-doing the same query all over. + * + * @param string $context option context + * @param string $name plugin name + * @return integer option id + */ + final protected function get_option_id($context, $name) + { + $key = "{$context}_{$name}"; + + if ( array_key_exists($key, $this->option_info) + && array_key_exists('oid', $this->option_info[$key]) ) + { + return $this->option_info[$key]['oid']; + } + + // load all OIDs for this plugin from the database + $this->option_info = array(); + $query = "SELECT oid, oname, ocontext, odef FROM %s WHERE opid=%d;"; + $query = sprintf($query, sql_table('plugin_option_desc'), $this->plugid); + $result = DB::getResult($query); + foreach ( $result as $row ) + { + $k = $row['ocontext'] . '_' . $row['oname']; + $this->option_info[$k] = array('oid' => $row['oid'], 'default' => $row['odef']); + } + $result->closeCursor(); + + return $this->option_info[$key]['oid']; + } + final protected function get_default_value($context, $name) + { + $key = $context . '_' . $name; + + if ( array_key_exists($key, $this->option_info) + && array_key_exists('default', $this->option_info[$key]) ) + { + return $this->option_info[$key]['default']; + } + return; + } + + /** + * NucleusPlugin::delete_option_values() + * Deletes all option values for a given context and contextid + * (used when e.g. a blog, member or category is deleted) + * + *@static + *@param String $context global/blog/category/item/member + *@param Integer $contextid ID + *@return Void + */ + static public function delete_option_values($context, $contextid) + { + // delete all associated plugin options + $aOIDs = array(); + // find ids + $query = "SELECT oid FROM %s WHERE ocontext=%s;"; + $query = sprintf($query, sql_table('plugin_option_desc'), DB::quoteValue($context)); + + $result = DB::getResult($query); + foreach ( $result as $row ) + { + array_push($aOIDs, $row['oid']); + } + $result->closeCursor(); + // delete those options. go go go + if ( count($aOIDs) > 0 ) + { + $query = "DELETE FROM %s WHERE oid in (%s) and ocontextid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), implode(',',$aOIDs), (integer) $contextid); + DB::execute($query); + } + return; + } + + /** + * NucleusPlugin::getOptionMeta() + * splits the option's typeextra field (at ;'s) to split the meta collection + * + * @static + * @param string $typeExtra the value of the typeExtra field of an option + * @return array array of the meta-key/value-pairs + */ + static public function getOptionMeta($typeExtra) + { + $meta = array(); + + /* 1. if $typeExtra includes delimiter ';', split it to tokens */ + $tokens = preg_split('#;#', $typeExtra); + + /* + * 2. if each of tokens includes "=", it consists of key => value + * else it's 'select' option + */ + foreach ( $tokens as $token ) + { + $matches = array(); + if ( preg_match("#^([^=]+)?=([^=]+)?$#", $token, $matches) ) + { + $meta[$matches[1]] = $matches[2]; + } + else + { + $meta['select'] = $token; + } + } + return $meta; + } + + /** + * NucleusPlugin::getOptionSelectValues() + * filters the selectlists out of the meta collection + * + * @static + * @param string $typeExtra the value of the typeExtra field of an option + * @return string the selectlist + */ + static public function getOptionSelectValues($typeExtra) + { + $meta = NucleusPlugin::getOptionMeta($typeExtra); + + if ( array_key_exists('select', $meta) ) + { + return $meta['select']; + } + return; + } + + /** + * checks if the eventlist in the database is up-to-date + * @return bool if it is up-to-date it return true, else false + * @author TeRanEX + */ + public function subscribtionListIsUptodate() + { + $res = DB::getResult('SELECT event FROM '.sql_table('plugin_event').' WHERE pid = '.$this->plugid); + $ev = array(); + foreach ( $res as $row ) + { + array_push($ev, $row['event']); + } + if ( count($ev) != count($this->getEventList()) ) + { + return false; + } + $d = array_diff($ev, $this->getEventList()); + if ( count($d) > 0 ) + { + // there are differences so the db is not up-to-date + return false; + } + return true; + } + + /** + * NucleusPlugin::apply_plugin_options() + * Update its entry in database table + * + * @static + * @param $options: array ( 'oid' => array( 'contextid' => 'value')) + * (taken from request using requestVar()) + * @param $new_contextid: integer (accepts a contextid when it is for a new + * contextid there was no id available at the moment of writing the + * formcontrols into the page (by ex: itemOptions for new item) + * @return void + */ + static public function apply_plugin_options(&$options, $new_contextid = 0) + { + global $manager; + + if ( !is_array($options) ) + { + return; + } + + foreach ( $options as $oid => $values ) + { + // get option type info + $query = "SELECT opid, oname, ocontext, otype, oextra, odef FROM %s WHERE oid=%d;"; + $query = sprintf($query, sql_table('plugin_option_desc'), (integer) $oid); + $result = DB::getRow($query); + if ( $result ) + { + foreach ( $values as $id => $value ) + { + // decide wether we are using the contextid of newContextid + if ( $new_contextid != 0 ) + { + $contextid = $new_contextid; + } + else + { + $contextid = $id; + } + + // retreive any metadata + $meta = NucleusPlugin::getOptionMeta($result['oextra']); + + // if the option is readonly or hidden it may not be saved + if ( array_key_exists('access', $meta) + && in_array($meta['access'], array('readonly', 'hidden')) ) + { + return; + } + + // value comes from request + $value = undoMagic($value); + + /* validation the value according to its type */ + switch ( $result['otype'] ) + { + case 'yesno': + if ( ($value != 'yes') && ($value != 'no') ) + { + $value = 'no'; + } + break; + case 'text': + case 'select': + if ( array_key_exists('datatype', $meta) + && ($meta['datatype'] == 'numerical') && ($value != (integer) $value) ) + { + $value = (integer) $result['odef']; + } + break; + case 'password': + case 'textarea': + default: + break; + } + + /* + * trigger event PrePluginOptionsUpdate to give the plugin the + * possibility to change/validate the new value for the option + */ + $data = array( + 'context' => $result['ocontext'], + 'plugid' => $result['opid'], + 'optionname' => $result['oname'], + 'contextid' => $contextid, + 'value' => &$value); + $manager->notify('PrePluginOptionsUpdate', $data); + + // delete and insert its fields of table in database + $query = "DELETE FROM %s WHERE oid=%d AND ocontextid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid); + DB::execute($query); + $query = "INSERT INTO %s (oid, ocontextid, ovalue) VALUES (%d, %d, %s);"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid, DB::quoteValue($value)); + DB::execute($query); + + // clear option value cache if the plugin object is already loaded + $plugin=& $manager->pidLoaded($result['opid']); + if ( $plugin ) + { + $plugin->clearOptionValueCache(); + } + + continue; + } + } + continue; + } + return; + } +} ++======= + if the plugin uses the sql_table() method to get table names + * 'HelpPage' -> if the plugin provides a helppage + * 'SqlApi' -> if the plugin uses the complete sql_* or DB::* api (must also require nucleuscms 3.5) + */ + public function supportsFeature($feature) + { + return 0; + } + + /** + * Report a list of plugin that is required to final public function + * + * @returns an array of names of plugin, an empty array indicates no dependency + */ + public function getPluginDep() + { + return array(); + } + + // these helper final public functions should not be redefined in your plugin + + /** + * Creates a new option for this plugin + * + * @param name + * A string uniquely identifying your option. (max. length is 20 characters) + * @param description + * A description that will show up in the nucleus admin area (max. length: 255 characters) + * @param type + * Either 'text', 'yesno' or 'password' + * This info is used when showing 'edit plugin options' screens + * @param value + * Initial value for the option (max. value length is 128 characters) + */ + final public function createOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('global', $name, $desc, $type, $defValue, $typeExtras); + } + + final public function createBlogOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('blog', $name, $desc, $type, $defValue, $typeExtras); + } + + final public function createMemberOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('member', $name, $desc, $type, $defValue, $typeExtras); + } + + final public function createCategoryOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('category', $name, $desc, $type, $defValue, $typeExtras); + } + + final public function createItemOption($name, $desc, $type, $defValue = '', $typeExtras = '') + { + return $this->create_option('item', $name, $desc, $type, $defValue, $typeExtras); + } + + /** + * Removes the option from the database + * + * Note: Options get erased automatically on plugin uninstall + */ + final public function deleteOption($name) + { + return $this->delete_option('global', $name); + } + + final public function deleteBlogOption($name) + { + return $this->delete_option('blog', $name); + } + + final public function deleteMemberOption($name) + { + return $this->delete_option('member', $name); + } + + final public function deleteCategoryOption($name) + { + return $this->delete_option('category', $name); + } + + final public function deleteItemOption($name) + { + return $this->delete_option('item', $name); + } + + /** + * Sets the value of an option to something new + */ + final public function setOption($name, $value) + { + return $this->set_option('global', 0, $name, $value); + } + + final public function setBlogOption($blogid, $name, $value) + { + return $this->set_option('blog', $blogid, $name, $value); + } + + final public function setMemberOption($memberid, $name, $value) + { + return $this->set_option('member', $memberid, $name, $value); + } + + final public function setCategoryOption($catid, $name, $value) + { + return $this->set_option('category', $catid, $name, $value); + } + + final public function setItemOption($itemid, $name, $value) { + return $this->set_option('item', $itemid, $name, $value); + } + + /** + * Retrieves the current value for an option + */ + final public function getOption($name) + { + // only request the options the very first time. On subsequent requests + // the static collection is used to save SQL queries. + if ( $this->plugin_options == 0 ) + { + $this->plugin_options = array(); + + $query = "SELECT d.oname as name, o.ovalue as value FROM %s o, %s d WHERE d.opid=%d AND d.oid=o.oid;"; + $query = sprintf($query, sql_table('plugin_option'), sql_table('plugin_option_desc'), (integer) $this->plugid); + $result = DB::getResult($query); + foreach ( $result as $row ) + { + $this->plugin_options[strtolower($row['name'])] = $row['value']; + } + } + if ( isset($this->plugin_options[strtolower($name)]) ) + { + return $this->plugin_options[strtolower($name)]; + } + else + { + return $this->get_option('global', 0, $name); + } + } + + final public function getBlogOption($blogid, $name) + { + return $this->get_option('blog', $blogid, $name); + } + + final public function getMemberOption($memberid, $name) + { + return $this->get_option('member', $memberid, $name); + } + + final public function getCategoryOption($catid, $name) + { + return $this->get_option('category', $catid, $name); + } + + final public function getItemOption($itemid, $name) + { + return $this->get_option('item', $itemid, $name); + } + + /** + * Retrieves an associative array with the option value for each + * context id + */ + final public function getAllBlogOptions($name) + { + return $this->get_all_options('blog', $name); + } + + final public function getAllMemberOptions($name) + { + return $this->get_all_options('member', $name); + } + + final public function getAllCategoryOptions($name) + { + return $this->get_all_options('category', $name); + } + + final public function getAllItemOptions($name) + { + return $this->get_all_options('item', $name); + } + + /** + * Retrieves an indexed array with the top (or bottom) of an option + * (delegates to getOptionTop()) + */ + final public function getBlogOptionTop($name, $amount = 10, $sort = 'desc') + { + return $this->get_option_top('blog', $name, $amount, $sort); + } + + final public function getMemberOptionTop($name, $amount = 10, $sort = 'desc') + { + return $this->get_option_top('member', $name, $amount, $sort); + } + + final public function getCategoryOptionTop($name, $amount = 10, $sort = 'desc') + { + return $this->get_option_top('category', $name, $amount, $sort); + } + + final public function getItemOptionTop($name, $amount = 10, $sort = 'desc') + { + return $this->get_option_top('item', $name, $amount, $sort); + } + + /** + * NucleusPlugin::getID() + * get id for this plugin + * + * @access public + * @param void + * @return integer this plugid id + */ + final public function getID() + { + return (integer) $this->plugid; + } + + /** + * NucleusPlugin::setID() + * set favorite id for this plugin + * + * @access public + * @param integer $plugid favorite id for plugin + * @return void + */ + final public function setID($plugid) + { + $this->plugid = (integer) $plugid; + return; + } + + /** + * Returns the URL of the admin area for this plugin (in case there's + * no such area, the returned information is invalid) + * + * public + */ + final public function getAdminURL() + { + global $CONF; + return $CONF['PluginURL'] . $this->getShortName() . '/'; + } + + /** + * Returns the directory where the admin directory is located and + * where the plugin can maintain his extra files + * + * public + */ + final public function getDirectory() + { + global $DIR_PLUGINS; + return $DIR_PLUGINS . $this->getShortName() . '/'; + } + + /** + * Derives the short name for the plugin from the classname (all + * lowercase) + * + * public + */ + final public function getShortName() + { + return str_replace('np_','',strtolower(get_class($this))); + } + + /** + * Clears the option value cache which saves the option values during + * the plugin execution. This function is usefull if the options has + * changed during the plugin execution (especially in association with + * the PrePluginOptionsUpdate and the PostPluginOptionsUpdate events) + * + * public + **/ + final public function clearOptionValueCache() + { + $this->option_values = array(); + $this->plugin_options = 0; + return; + } + + // internal functions of the class starts here + protected $option_values; // oid_contextid => value + protected $option_info; // context_name => array('oid' => ..., 'default' => ...) + protected $plugin_options; // see getOption() + protected $plugid; // plugin id + + /** + * Class constructor: Initializes some internal data + */ + public function __construct() + { + $this->option_values = array(); // oid_contextid => value + $this->option_info = array(); // context_name => array('oid' => ..., 'default' => ...) + $this->plugin_options = 0; + } + + /** + * Retrieves an array of the top (or bottom) of an option from a plugin. + * @author TeRanEX + * @param string $context the context for the option: item, blog, member,... + * @param string $name the name of the option + * @param int $amount how many rows must be returned + * @param string $sort desc or asc + * @return array array with both values and contextid's + * @access private + */ + final protected function get_option_top($context, $name, $amount = 10, $sort = 'desc') + { + if ( ($sort != 'desc') && ($sort != 'asc') ) + { + $sort= 'desc'; + } + + $oid = $this->get_option_id($context, $name); + + // retrieve the data and return + $query = "SELECT otype, oextra FROM %s WHERE oid = %d;"; + $query = sprintf($query, sql_table('plugin_option_desc'), $oid); + $row = DB::getRow($query); + + if ( ($this->optionCanBeNumeric($row['otype'])) && ($row['oextra'] == 'number' ) ) + { + $orderby = 'CAST(ovalue AS SIGNED)'; + } + else + { + $orderby = 'ovalue'; + } + $query = "SELECT ovalue value, ocontextid id FROM %s WHERE oid = %d ORDER BY %s %s LIMIT 0,%d;"; + $query = sprintf($query, sql_table('plugin_option'), $oid, $orderby, $sort, (integer) $amount); + $result = DB::getResult($query); + + // create the array + $i = 0; + $top = array(); + foreach( $result as $row ) + { + $top[$i++] = $row; + } + + // return the array (duh!) + return $top; + } + + /** + * Creates an option in the database table plugin_option_desc + * + * private + */ + final protected function create_option($context, $name, $desc, $type, $defValue, $typeExtras = '') + { + // create in plugin_option_desc + $query = 'INSERT INTO ' . sql_table('plugin_option_desc') + .' (opid, oname, ocontext, odesc, otype, odef, oextra)' + .' VALUES ('.intval($this->plugid) + .', '.DB::quoteValue($name) + .', '.DB::quoteValue($context) + .', '.DB::quoteValue($desc) + .', '.DB::quoteValue($type) + .', '.DB::quoteValue($defValue) + .', '.DB::quoteValue($typeExtras).')'; + DB::execute($query); + $oid = DB::getInsertId(); + + $key = $context . '_' . $name; + $this->option_info[$key] = array('oid' => $oid, 'default' => $defValue); + return 1; + } + + /** + * Deletes an option from the database tables + * plugin_option and plugin_option_desc + * + * private + */ + final protected function delete_option($context, $name) + { + $oid = $this->get_option_id($context, $name); + if ( !$oid ) + { + return 0; // no such option + } + + // delete all things from plugin_option + $query = "DELETE FROM %s WHERE oid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid); + DB::execute($query); + + // delete entry from plugin_option_desc + $query = "DELETE FROM %s WHERE oid=%d;"; + $query = sprintf($query, sql_table('plugin_option_desc'), $oid); + DB::execute($query); + + // clear from cache + unset($this->option_info["{$context}_{$name}"]); + $this->option_values = array(); + return 1; + } + + /** + * Update an option in the database table plugin_option + * + * returns: 1 on success, 0 on failure + * private + */ + final protected function set_option($context, $contextid, $name, $value) + { + global $manager; + + $oid = $this->get_option_id($context, $name); + if ( !$oid ) + { + return 0; + } + + // check if context id exists + switch ( $context ) + { + case 'member': + if ( !Member::existsID($contextid) ) + { + return 0; + } + break; + case 'blog': + if ( !$manager->existsBlogID($contextid) ) + { + return 0; + } + break; + case 'category': + if ( !$manager->existsCategory($contextid) ) + { + return 0; + } + break; + case 'item': + if ( !$manager->existsItem($contextid, true, true) ) + { + return 0; + } + break; + case 'global': + if ( $contextid != 0 ) + { + return 0; + } + break; + } + + // update plugin_option + $query = "DELETE FROM %s WHERE oid=%d and ocontextid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid); + DB::execute($query); + + $query = "INSERT INTO %s (ovalue, oid, ocontextid) VALUES (%s, %d, %d);"; + $query = sprintf($query, sql_table('plugin_option'), DB::quoteValue($value), $oid, $contextid); + DB::execute($query); + + // update cache + $this->option_values["{$oid}_{$contextid}"] = $value; + if ( $context == 'global' ) + { + $this->plugin_options[strtolower($name)] = $value; + } + + return 1; + } + + /** + * Get an option from Cache or database + * - if not in the option Cache read it from the database + * - if not in the database write default values into the database + * + * private + */ + final protected function get_option($context, $contextid, $name) + { + $oid = $this->get_option_id($context, $name); + if ( !$oid ) + { + return ''; + } + + $key = "{$oid}_{$contextid}"; + + if ( isset($this->option_values[$key]) ) + { + return $this->option_values[$key]; + } + + // get from DB + $query = "SELECT ovalue FROM %s WHERE oid=%d and ocontextid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid); + $result = DB::getResult($query); + + if ( !$result || ($result->rowCount() == 0) ) + { + // fill DB with default value + $this->option_values[$key] = $this->get_default_value($context, $name); + $query = "INSERT INTO %s (oid, ocontextid, ovalue) VALUES (%d, %d, %s);"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid, DB::quoteValue($this->option_values[$key])); + DB::execute($query); + } + else + { + $row = $result->fetch(); + $this->option_values[$key] = $row['ovalue']; + } + + return $this->option_values[$key]; + } + + /** + * Returns assoc array with all values for a given option + * (one option per possible context id) + * + * private + */ + final protected function get_all_options($context, $name) + { + $oid = $this->get_option_id($context, $name); + if ( !$oid ) + { + return array(); + } + $default_value = $this->get_default_value($context, $name); + + $options = array(); + $query = "SELECT %s as contextid FROM %s;"; + switch ( $context ) + { + case 'blog': + $query = sprintf($query, 'bnumber', sql_table('blog')); + break; + case 'category': + $query = sprintf($query, 'catid', sql_table('category')); + break; + case 'member': + $query = sprintf($query, 'mnumber', sql_table('member')); + break; + case 'item': + $query = sprintf($query, 'inumber', sql_table('item')); + break; + } + + $result = DB::getResult($query); + if ( $result ) + { + foreach ( $result as $row ) + { + $options[$row['contextid']] = $default_value; + } + } + + $query = "SELECT ocontextid, ovalue FROM %s WHERE oid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), $oid); + $result = DB::getResult($query); + foreach ( $result as $row ) + { + $options[$row['ocontextid']] = $row['ovalue']; + } + + return $options; + } + + /** + * NucleusPlugin::get_option_id + * + * Gets the 'option identifier' that corresponds to a given option name. + * When this method is called for the first time, all the OIDs for the plugin + * are loaded into memory, to avoid re-doing the same query all over. + * + * @param string $context option context + * @param string $name plugin name + * @return integer option id + */ + final protected function get_option_id($context, $name) + { + $key = "{$context}_{$name}"; + + if ( array_key_exists($key, $this->option_info) + && array_key_exists('oid', $this->option_info[$key]) ) + { + return $this->option_info[$key]['oid']; + } + + // load all OIDs for this plugin from the database + $this->option_info = array(); + $query = "SELECT oid, oname, ocontext, odef FROM %s WHERE opid=%d;"; + $query = sprintf($query, sql_table('plugin_option_desc'), $this->plugid); + $result = DB::getResult($query); + foreach ( $result as $row ) + { + $k = $row['ocontext'] . '_' . $row['oname']; + $this->option_info[$k] = array('oid' => $row['oid'], 'default' => $row['odef']); + } + $result->closeCursor(); + + return $this->option_info[$key]['oid']; + } + final protected function get_default_value($context, $name) + { + $key = $context . '_' . $name; + + if ( array_key_exists($key, $this->option_info) + && array_key_exists('default', $this->option_info[$key]) ) + { + return $this->option_info[$key]['default']; + } + return; + } + + /** + * NucleusPlugin::delete_option_values() + * Deletes all option values for a given context and contextid + * (used when e.g. a blog, member or category is deleted) + * + *@static + *@param String $context global/blog/category/item/member + *@param Integer $contextid ID + *@return Void + */ + static public function delete_option_values($context, $contextid) + { + // delete all associated plugin options + $aOIDs = array(); + // find ids + $query = "SELECT oid FROM %s WHERE ocontext=%s;"; + $query = sprintf($query, sql_table('plugin_option_desc'), DB::quoteValue($context)); + + $result = DB::getResult($query); + foreach ( $result as $row ) + { + array_push($aOIDs, $row['oid']); + } + $result->closeCursor(); + // delete those options. go go go + if ( count($aOIDs) > 0 ) + { + $query = "DELETE FROM %s WHERE oid in (%s) and ocontextid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), implode(',',$aOIDs), (integer) $contextid); + DB::execute($query); + } + return; + } + + /** + * NucleusPlugin::getOptionMeta() + * splits the option's typeextra field (at ;'s) to split the meta collection + * + * @static + * @param string $typeExtra the value of the typeExtra field of an option + * @return array array of the meta-key/value-pairs + */ + static public function getOptionMeta($typeExtra) + { + $meta = array(); + + /* 1. if $typeExtra includes delimiter ';', split it to tokens */ + $tokens = preg_split('#;#', $typeExtra); + + /* + * 2. if each of tokens includes "=", it consists of key => value + * else it's 'select' option + */ + foreach ( $tokens as $token ) + { + $matches = array(); + if ( preg_match("#^([^=]+)?=([^=]+)?$#", $token, $matches) ) + { + $meta[$matches[1]] = $matches[2]; + } + else + { + $meta['select'] = $token; + } + } + return $meta; + } + + /** + * NucleusPlugin::getOptionSelectValues() + * filters the selectlists out of the meta collection + * + * @static + * @param string $typeExtra the value of the typeExtra field of an option + * @return string the selectlist + */ + static public function getOptionSelectValues($typeExtra) + { + $meta = NucleusPlugin::getOptionMeta($typeExtra); + + if ( array_key_exists('select', $meta) ) + { + return $meta['select']; + } + return; + } + + /** + * checks if the eventlist in the database is up-to-date + * @return bool if it is up-to-date it return true, else false + * @author TeRanEX + */ + public function subscribtionListIsUptodate() + { + $res = DB::getResult('SELECT event FROM '.sql_table('plugin_event').' WHERE pid = '.$this->plugid); + $ev = array(); + foreach ( $res as $row ) + { + array_push($ev, $row['event']); + } + if ( count($ev) != count($this->getEventList()) ) + { + return false; + } + $d = array_diff($ev, $this->getEventList()); + if ( count($d) > 0 ) + { + // there are differences so the db is not up-to-date + return false; + } + return true; + } + + /** + * NucleusPlugin::apply_plugin_options() + * Update its entry in database table + * + * @static + * @param $options: array ( 'oid' => array( 'contextid' => 'value')) + * (taken from request using requestVar()) + * @param $new_contextid: integer (accepts a contextid when it is for a new + * contextid there was no id available at the moment of writing the + * formcontrols into the page (by ex: itemOptions for new item) + * @return void + */ + static public function apply_plugin_options(&$options, $new_contextid = 0) + { + global $manager; + + if ( !is_array($options) ) + { + return; + } + + foreach ( $options as $oid => $values ) + { + // get option type info + $query = "SELECT opid, oname, ocontext, otype, oextra, odef FROM %s WHERE oid=%d;"; + $query = sprintf($query, sql_table('plugin_option_desc'), (integer) $oid); + $result = DB::getRow($query); + if ( $result ) + { + foreach ( $values as $id => $value ) + { + // decide wether we are using the contextid of newContextid + if ( $new_contextid != 0 ) + { + $contextid = $new_contextid; + } + else + { + $contextid = $id; + } + + // retreive any metadata + $meta = NucleusPlugin::getOptionMeta($result['oextra']); + + // if the option is readonly or hidden it may not be saved + if ( array_key_exists('access', $meta) + && in_array($meta['access'], array('readonly', 'hidden')) ) + { + return; + } + + // value comes from request + $value = undoMagic($value); + + /* validation the value according to its type */ + switch ( $result['otype'] ) + { + case 'yesno': + if ( ($value != 'yes') && ($value != 'no') ) + { + $value = 'no'; + } + break; + case 'text': + case 'select': + if ( array_key_exists('datatype', $meta) + && ($meta['datatype'] == 'numerical') && ($value != (integer) $value) ) + { + $value = (integer) $result['odef']; + } + break; + case 'password': + case 'textarea': + default: + break; + } + + /* + * trigger event PrePluginOptionsUpdate to give the plugin the + * possibility to change/validate the new value for the option + */ + $data = array( + 'context' => $result['ocontext'], + 'plugid' => $result['opid'], + 'optionname' => $result['oname'], + 'contextid' => $contextid, + 'value' => &$value); + $manager->notify('PrePluginOptionsUpdate', $data); + + // delete and insert its fields of table in database + $query = "DELETE FROM %s WHERE oid=%d AND ocontextid=%d;"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid); + DB::execute($query); + $query = "INSERT INTO %s (oid, ocontextid, ovalue) VALUES (%d, %d, %s);"; + $query = sprintf($query, sql_table('plugin_option'), (integer) $oid, (integer) $contextid, DB::quoteValue($value)); + DB::execute($query); + + // clear option value cache if the plugin object is already loaded + $plugin=& $manager->pidLoaded($result['opid']); + if ( $plugin ) + { + $plugin->clearOptionValueCache(); + } + + continue; + } + } + continue; + } + return; + } + } ++>>>>>>> skinnable-master diff --combined nucleus/libs/PLUGINADMIN.php index 56f2df6,9d2b208..e1fce52 --- a/nucleus/libs/PLUGINADMIN.php +++ b/nucleus/libs/PLUGINADMIN.php @@@ -1,160 -1,167 +1,330 @@@ ++<<<<<<< HEAD +strFullName = "NP_{$pluginName}"; + + // check if plugin exists and is installed + if ( !$manager->pluginInstalled($this->strFullName) ) + { + doError(_ERROR_INVALID_PLUGIN); + } + + $this->plugin =& $manager->getPlugin($this->strFullName); + $this->bValid = $this->plugin; + + if ( !$this->bValid ) + { + doError(_ERROR_INVALID_PLUGIN); + } + + $this->admin = new Admin(); + $this->admin->action = "plugin_{$pluginName}"; + return; + } + + /** + * PluginAdmin::start() + * + * @param string $extraHead child elements for header element + * @return void + */ + public function start($extraHead = '') + { + global $CONF; + $strBaseHref = ''; + $extraHead .= $strBaseHref; + + $this->admin->pagehead($extraHead); + return; + } + + /** + * PluginAdmin::end() + * + * @param void + * @return void + */ + public function end() + { + $this->_AddTicketByJS(); + $this->admin->pagefoot(); + return; + } + + /** + * PluginAdmin::_AddTicketByJS() + * Add ticket when not used in plugin's admin page + * to avoid CSRF. + * + * @param void + * @return void + */ + public function _AddTicketByJS() + { + global $CONF,$ticketforplugin; + if ( !($ticket=$ticketforplugin['ticket']) ) + { + return; + } + $ticket=Entity::hsc($ticket); + +?>strFullName = "NP_{$pluginName}"; + + // check if plugin exists and is installed + if ( !$manager->pluginInstalled($this->strFullName) ) + { + doError(_ERROR_INVALID_PLUGIN); + return; + } + + $this->plugin = &$manager->getPlugin($this->strFullName); + $this->bValid = $this->plugin; + + if ( !$this->bValid ) + { + doError(_ERROR_INVALID_PLUGIN); + return; + } + + Admin::initialize(); + Admin::$action = "plugin_{$pluginName}"; + + return; + } + + /** + * PluginAdmin::start() + * + * @param string $extraHead child elements for header element + * @return void + */ + public function start($extraHead = '') + { + global $CONF; + $this->extrahead = $extraHead . '' . "\n"; + ob_start(); + return; + } + + /** + * PluginAdmin::end() + * + * @param void + * @return void + */ + public function end() + { + $this->AddTicketByJS(); + $contents = ob_get_contents(); + ob_end_clean(); + $this->skinContents = '<%pagehead%>' . $contents . '<%pagefoot%>'; + Admin::action_PluginAdmin($this->skinContents, $this->extrahead); + return; + } + + /** + * PluginAdmin::_AddTicketByJS() + * Add ticket when not used in plugin's admin page + * to avoid CSRF. + * + * @param void + * @return void + */ + private function AddTicketByJS() + { + global $CONF,$ticketforplugin; + if ( !($ticket = $ticketforplugin['ticket']) ) + { + return; + } + $ticket=Entity::hsc($ticket); + + ?>>>>>>> skinnable-master diff --combined nucleus/libs/SEARCH.php index ae28362,534152f..81edfb5 --- a/nucleus/libs/SEARCH.php +++ b/nucleus/libs/SEARCH.php @@@ -1,221 -1,221 +1,445 @@@ ++<<<<<<< HEAD +,=,?,!,#,^,(,),[,\],:,;,\\\,%]/","",$text); + $this->querystring = $text; + $this->marked = $this->boolean_mark_atoms($text); + $this->inclusive = $this->boolean_inclusive_atoms($text); + $this->blogs = array(); + + // get all public searchable blogs, no matter what, include the current blog allways. + $res = DB::getResult('SELECT bnumber FROM '.sql_table('blog').' WHERE bincludesearch=1 '); + foreach ( $res as $row ) + $this->blogs[] = intval($row['bnumber']); + } + + function boolean_sql_select($match){ + if (i18n::strlen($this->inclusive) > 0) { + /* build sql for determining score for each record */ + $result=preg_split("# #",$this->inclusive); + for($cth=0;$cth=4){ + $stringsum_long .= " $result[$cth] "; + }else{ + $stringsum_a[] = ' '.$this->boolean_sql_select_short($result[$cth],$match).' '; + } + } + + if(i18n::strlen($stringsum_long)>0){ + $stringsum_long = DB::quoteValue($stringsum_long); + $stringsum_a[] = " match ({$match}) against ({$stringsum_long}) "; + } + + $stringsum .= implode("+",$stringsum_a); + return $stringsum; + } + } + + function boolean_inclusive_atoms($string){ + $result = trim($string); + $result = preg_replace("#([[:space:]]{2,})#", ' ', $result); + + # replaced eregi_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0 + # just added delimiters to regex and the 'i' for case-insensitive matching + + /* convert normal boolean operators to shortened syntax */ + $result = preg_replace('# not #i', ' -', $result); + $result = preg_replace('# and #i', ' ', $result); + $result = preg_replace('# or #i', ',', $result); + + /* drop unnecessary spaces */ + $result = str_replace(' ,', ',', $result); + $result = str_replace(', ', ',', $result); + $result = str_replace('- ', '-', $result); + $result = str_replace('+', '', $result); + + /* strip exlusive atoms */ + $result = preg_replace( + "#\-\([A-Za-z0-9]{1,}[A-Za-z0-9\-\.\_\,]{0,}\)#", + '', + $result); + + $result = str_replace('(', ' ', $result); + $result = str_replace(')', ' ', $result); + $result = str_replace(',', ' ', $result); + + return $result; + } + + function boolean_sql_where($match){ + + $result = $this->marked; + + $this->boolean_sql_where_cb1($match); // set the static $match + + $result = preg_replace_callback( + + "/foo\[\(\'([^\)]{4,})\'\)\]bar/", + + array($this,'boolean_sql_where_cb1'), + + $result); + + $this->boolean_sql_where_cb2($match); // set the static $match + + $result = preg_replace_callback( + + "/foo\[\(\'([^\)]{1,3})\'\)\]bar/", + + array($this,'boolean_sql_where_cb2'), + + $result); + + return $result; + + } + + function boolean_sql_where_cb1($matches){ + + static $match; + + if (!is_array($matches)) $match=$matches; + + else return ' match ('.$match.') against ('.DB::quoteValue($matches[1]).') > 0 '; + + } + + function boolean_sql_where_cb2($matches){ + + static $match; + + if (!is_array($matches)) $match=$matches; + + else return ' ('.$this->boolean_sql_where_short($matches[1], $match).') '; + + } + + function boolean_mark_atoms($string){ + $result = trim($string); + $result = preg_replace("/([[:space:]]{2,})/",' ',$result); + + # replaced eregi_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0 + # just added delimiters to regex and the 'i' for case-insensitive matching + + /* convert normal boolean operators to shortened syntax */ + $result = preg_replace('# not #i', ' -', $result); + $result = preg_replace('# and #i', ' ', $result); + $result = preg_replace('# or #i', ',', $result); + + /* strip excessive whitespace */ + $result = str_replace('( ', '(', $result); + $result = str_replace(' )', ')', $result); + $result = str_replace(', ', ',', $result); + $result = str_replace(' ,', ',', $result); + $result = str_replace('- ', '-', $result); + $result = str_replace('+', '', $result); + + // remove double spaces (we might have introduced some new ones above) + $result = trim($result); + $result = preg_replace("#([[:space:]]{2,})#", ' ', $result); + + /* apply arbitrary function to all 'word' atoms */ + + $result_a = preg_split('# #', $result); + + for($word = 0;$word ++======= + ,=,?,!,#,^,(,),[,\],:,;,\\\,%]/","",$text); + $this->querystring = $text; + $this->marked = $this->boolean_mark_atoms($text); + $this->inclusive = $this->boolean_inclusive_atoms($text); + $this->blogs = array(); + + // get all public searchable blogs, no matter what, include the current blog allways. + $res = DB::getResult('SELECT bnumber FROM '.sql_table('blog').' WHERE bincludesearch=1 '); + foreach ( $res as $row ) + $this->blogs[] = intval($row['bnumber']); + } + + function boolean_sql_select($match){ + if (i18n::strlen($this->inclusive) > 0) { + /* build sql for determining score for each record */ + $result=preg_split("# #",$this->inclusive); + for($cth=0;$cth=4){ + $stringsum_long .= " $result[$cth] "; + }else{ + $stringsum_a[] = ' '.$this->boolean_sql_select_short($result[$cth],$match).' '; + } + } + + if(i18n::strlen($stringsum_long)>0){ + $stringsum_long = DB::quoteValue($stringsum_long); + $stringsum_a[] = " match ({$match}) against ({$stringsum_long}) "; + } + + $stringsum .= implode("+",$stringsum_a); + return $stringsum; + } + } + + function boolean_inclusive_atoms($string){ + $result = trim($string); + $result = preg_replace("#([[:space:]]{2,})#", ' ', $result); + + # replaced eregi_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0 + # just added delimiters to regex and the 'i' for case-insensitive matching + + /* convert normal boolean operators to shortened syntax */ + $result = preg_replace('# not #i', ' -', $result); + $result = preg_replace('# and #i', ' ', $result); + $result = preg_replace('# or #i', ',', $result); + + /* drop unnecessary spaces */ + $result = str_replace(' ,', ',', $result); + $result = str_replace(', ', ',', $result); + $result = str_replace('- ', '-', $result); + $result = str_replace('+', '', $result); + + /* strip exlusive atoms */ + $result = preg_replace( + "#\-\([A-Za-z0-9]{1,}[A-Za-z0-9\-\.\_\,]{0,}\)#", + '', + $result); + + $result = str_replace('(', ' ', $result); + $result = str_replace(')', ' ', $result); + $result = str_replace(',', ' ', $result); + + return $result; + } + + function boolean_sql_where($match){ + + $result = $this->marked; + + $this->boolean_sql_where_cb1($match); // set the static $match + + $result = preg_replace_callback( + + "/foo\[\(\'([^\)]{4,})\'\)\]bar/", + + array($this,'boolean_sql_where_cb1'), + + $result); + + $this->boolean_sql_where_cb2($match); // set the static $match + + $result = preg_replace_callback( + + "/foo\[\(\'([^\)]{1,3})\'\)\]bar/", + + array($this,'boolean_sql_where_cb2'), + + $result); + + return $result; + + } + + function boolean_sql_where_cb1($matches){ + + static $match; + + if (!is_array($matches)) $match=$matches; + + else return ' match ('.$match.') against ('.DB::quoteValue($matches[1]).') > 0 '; + + } + + function boolean_sql_where_cb2($matches){ + + static $match; + + if (!is_array($matches)) $match=$matches; + + else return ' ('.$this->boolean_sql_where_short($matches[1], $match).') '; + + } + + function boolean_mark_atoms($string){ + $result = trim($string); + $result = preg_replace("/([[:space:]]{2,})/",' ',$result); + + # replaced eregi_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0 + # just added delimiters to regex and the 'i' for case-insensitive matching + + /* convert normal boolean operators to shortened syntax */ + $result = preg_replace('# not #i', ' -', $result); + $result = preg_replace('# and #i', ' ', $result); + $result = preg_replace('# or #i', ',', $result); + + /* strip excessive whitespace */ + $result = str_replace('( ', '(', $result); + $result = str_replace(' )', ')', $result); + $result = str_replace(', ', ',', $result); + $result = str_replace(' ,', ',', $result); + $result = str_replace('- ', '-', $result); + $result = str_replace('+', '', $result); + + // remove double spaces (we might have introduced some new ones above) + $result = trim($result); + $result = preg_replace("#([[:space:]]{2,})#", ' ', $result); + + /* apply arbitrary function to all 'word' atoms */ + + $result_a = preg_split('# #', $result); + + for($word = 0;$word ++>>>>>>> skinnable-master diff --combined nucleus/libs/SKIN.php index e6a8a8f,1cd58ea..55547be --- a/nucleus/libs/SKIN.php +++ b/nucleus/libs/SKIN.php @@@ -14,7 -14,7 +14,11 @@@ * * @license http://nucleuscms.org/license.txt GNU General Public License * @copyright Copyright (C) 2002-2009 The Nucleus Group ++<<<<<<< HEAD + * @version $Id: SKIN.php 1816 2012-05-03 01:40:10Z sakamocchi $ ++======= + * @version $Id: SKIN.php 1886 2012-06-17 08:27:27Z sakamocchi $ ++>>>>>>> skinnable-master */ if ( !function_exists('requestVar') ) @@@ -54,9 -54,7 +58,13 @@@ class Ski $this->id = (integer) $id; ++<<<<<<< HEAD + /* + * NOTE: include needed action class + */ ++======= + /* NOTE: include needed action class */ ++>>>>>>> skinnable-master if ( $action_class != 'Actions' ) { if ( !class_exists($action_class, FALSE) @@@ -338,13 -336,20 +346,30 @@@ // retrieve contents $contents = FALSE; ++<<<<<<< HEAD + if ( $type != 'fileparse' ) + { + $contents = $this->getContentFromDB($type); + } + else if ( $path !== '' && i18n::strpos(realpath($path), realpath("$DIR_NUCLEUS/../")) == 0 ) + { + $contents = $this->getContentFromFile($path); ++======= + if ( $type == 'pluginadmin' ) + { + $contents = $path; + } + else + { + if ( $type != 'fileparse' && $type != 'importAdmin') + { + $contents = $this->getContentFromDB($type); + } + else if ( $path !== '' && i18n::strpos(realpath($path), realpath("$DIR_NUCLEUS/../")) == 0 ) + { + $contents = $this->getContentFromFile($path); + } ++>>>>>>> skinnable-master } // use base skin if this skin does not have contents if ( $contents === FALSE ) @@@ -450,7 -455,7 +475,11 @@@ $res = DB::getValue($query); $skintypeexists = !empty($res); ++<<<<<<< HEAD + $skintypevalue = ($content == true); ++======= + $skintypevalue = !empty($content); ++>>>>>>> skinnable-master if( $skintypevalue && $skintypeexists ) { @@@ -459,39 -464,35 +488,65 @@@ 'type' => $type, 'content' => &$content ); ++<<<<<<< HEAD + + // PreUpdateSkinPart event + $manager->notify("PreUpdate{{$this->event_identifier}}Part", $data); + } + else if( $skintypevalue && !$skintypeexists ) + { + $data = array( + 'skinid' => $this->id, + 'type' => $type, + 'content' => &$content + ); + + $manager->notify("PreAdd{$this->event_identifier}Part", $data); + } + else if( !$skintypevalue && $skintypeexists ) ++======= + $manager->notify("PreUpdate{$this->event_identifier}Part", $data); + } + else if( $skintypevalue ) + { + $data = array( + 'skinid' => $this->id, + 'type' => $type, + 'content' => &$content + ); + $manager->notify("PreAdd{$this->event_identifier}Part", $data); + } + else if( $skintypeexists ) ++>>>>>>> skinnable-master { $data = array( 'skinid' => $this->id, 'type' => $type ); ++<<<<<<< HEAD + ++======= ++>>>>>>> skinnable-master $manager->notify("PreDelete{$this->event_identifier}Part", $data); } // delete old thingie ++<<<<<<< HEAD + $query = "DELETE FROM %s WHERE stype=%s and sdesc=%d"; ++======= + $query = "DELETE FROM %s WHERE stype=%s and sdesc=%d;"; ++>>>>>>> skinnable-master $query = sprintf($query, sql_table('skin'), DB::quoteValue($type), (integer) $this->id); DB::execute($query); // write new thingie if ( $content ) { ++<<<<<<< HEAD + $query = "INSERT INTO %s (scontent, stype, sdesc) VALUE (%s, %s, %d)"; ++======= + $query = "INSERT INTO %s (scontent, stype, sdesc) VALUES (%s, %s, %d);"; ++>>>>>>> skinnable-master $query = sprintf($query, sql_table('skin'), DB::quoteValue($content), DB::quoteValue($type), (integer) $this->id); DB::execute($query); } @@@ -499,32 -500,27 +554,54 @@@ if( $skintypevalue && $skintypeexists ) { $data = array( ++<<<<<<< HEAD + 'skinid' => $this->id, + 'type' => $type, + 'content' => &$content + ); + + // PostUpdateSkinPart event + $manager->notify("PostUpdate{$this->event_identifier}Part", $data); + } + else if( $skintypevalue && (!$skintypeexists) ) + { + $data = array( + 'skinid' => $this->id, + 'type' => $type, + 'content' => &$content + ); + + // PostAddSkinPart event + $manager->notify("PostAdd{$this->event_identifier}Part", $data); + } + else if( (!$skintypevalue) && $skintypeexists ) ++======= + 'skinid' => $this->id, + 'type' => $type, + 'content' => &$content + ); + $manager->notify("PostUpdate{$this->event_identifier}Part", $data); + } + else if( $skintypevalue ) + { + $data = array( + 'skinid' => $this->id, + 'type' => $type, + 'content' => &$content + ); + $manager->notify("PostAdd{$this->event_identifier}Part", $data); + } + else if( $skintypeexists ) ++>>>>>>> skinnable-master { $data = array( 'skinid' => $this->id, 'type' => $type ); ++<<<<<<< HEAD + ++======= ++>>>>>>> skinnable-master $manager->notify("PostDelete{$this->event_identifier}Part", $data); } return; @@@ -613,14 -609,14 +690,24 @@@ } /** ++<<<<<<< HEAD + * Skin::getDefaultTypes() ++======= + * Skin::getNormalTypes() ++>>>>>>> skinnable-master * * @param string void * @return array default skin types */ ++<<<<<<< HEAD + public function getDefaultTypes() + { + return call_user_func(array($this->action_class, 'getAvailableSkinTypes')); ++======= + public function getNormalTypes() + { + return call_user_func(array($this->action_class, 'getNormalSkinTypes')); ++>>>>>>> skinnable-master } /** @@@ -631,7 -627,7 +718,11 @@@ */ public function getAvailableTypes() { ++<<<<<<< HEAD + $default_skintypes = $this->getDefaultTypes(); ++======= + $default_skintypes = $this->getNormalTypes(); ++>>>>>>> skinnable-master $query = "SELECT stype FROM %s WHERE sdesc=%d;"; $query = sprintf($query, sql_table('skin'), (integer) $this->id); @@@ -659,7 -655,7 +750,11 @@@ * Skin::getAllowedActionsForType() * Get the allowed actions for a skin type * returns an array with the allowed actions ++<<<<<<< HEAD + * ++======= + * @return array allowed action types ++>>>>>>> skinnable-master * @param string $skintype type of the skin * @return array allowed action types */ diff --combined nucleus/libs/TEMPLATE.php index 8421d64,10af5d1..ea7a6ac --- a/nucleus/libs/TEMPLATE.php +++ b/nucleus/libs/TEMPLATE.php @@@ -1,292 -1,273 +1,568 @@@ ++<<<<<<< HEAD +id = intval($templateid); + return; + } + + /** + * Template::getID() + * + * @param void + * @return integer id for this instance of Template class + */ + public function getID() + { + return (integer) $this->id; + } + + /** + * Template::createFromName() + * + * @statc + * @param string $name template name + * @return object instance of Template class generated by the name + */ + static public function createFromName($name) + { + return new Template(Template::getIdFromName($name)); + } + + /** + * Template::getIdFromName() + * + * @static + * @param string $name template name + * @return integer id for the template + */ + static public function getIdFromName($name) + { + $name = DB::quoteValue($name); + $query = "SELECT tdnumber FROM %s WHERE tdname=%s"; + $query = sprintf($query, sql_table('template_desc'), $name); + return DB::getValue($query); + } + + /** + * Template::updateGeneralInfo() + * Updates the general information about the template + * + * @param string $name template name + * @param string $desc description for this template + * @return void + */ + public function updateGeneralInfo($name, $desc) + { + $query = "UPDATE %s SET tdname=%s, tddesc=%s WHERE tdnumber=%d"; + $query = sprintf($query, sql_table('template_desc'), DB::quoteValue($name), DB::quoteValue($desc), (integer) $this->getID()); + DB::execute($query); + return; + } + + /** + * Template::update() + * Updates the contents of one part of the template + * + * @param String $type value for nucleus_template.tpartname + * @param String $content value for nucleus_template.tcontent + * @return Void + */ + public function update($type, $content) + { + // delete old thingie + $query = "DELETE FROM %s WHERE tpartname=%s and tdesc=%d"; + $query = sprintf($query, sql_table('template'), DB::quoteValue($type), (integer) $this->getID()); + DB::execute($query); + + // write new thingie + if ( $content ) + { + $query = "INSERT %s (tcontent, tpartname, tdesc) VALUE (%s, %s, %d)"; + $query = sprintf($query, sql_table('template'), DB::quoteValue($content), DB::quoteValue($type), (integer) $this->getID()); + DB::execute($query); + } + return; + } + + /** + * Template::deleteAllParts() + * Deletes all template parts from the database + * + * @param void + * @return void + */ + public function deleteAllParts() + { + $query = "DELETE FROM %s WHERE tdesc=%d"; + $query = sprintf($query, sql_table('template'), (integer) $this->getID()); + DB::execute($query); + return; + } + + /** + * Template::createNew() + * Creates a new template + * + * @static + * @param string $name name for new template + * @param string $desc description for new template + * @return integer id for new template + */ + static public function createNew($name, $desc) + { + global $manager; + + $manager->notify( + 'PreAddTemplate', + array( + 'name' => &$name, + 'description' => &$desc + ) + ); + + DB::execute('INSERT INTO '.sql_table('template_desc').' (tdname, tddesc) VALUES (' . DB::quoteValue($name) . ',' . DB::quoteValue($desc) . ')'); + $newId = DB::getInsertId(); + + $manager->notify( + 'PostAddTemplate', + array( + 'templateid' => $newId, + 'name' => $name, + 'description' => $desc + ) + ); + + return $newId; + } + + /** + * Reads a template and returns an array with the parts. + * + * @static + * @param string $name name of the template file + * @return array template array + */ + static public function read($name) + { + global $manager; + $manager->notify( + 'PreTemplateRead', + array( + 'template' => &$name + ) + ); + + $query = "SELECT tpartname, tcontent FROM %s, %s WHERE tdesc=tdnumber and tdname=%s"; + $query = sprintf($query, sql_table('template_desc'), sql_table('template'), DB::quoteValue($name)); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $template[$row['tpartname']] = $row['tcontent']; + } + + /* + * TODO: this is appropriate or not? + */ + if ( array_key_exists('LOCALE', $template) && !empty($template['LOCALE']) ) + { + setlocale(LC_TIME, $template['LOCALE']); + } + else + { + setlocale(LC_TIME,''); + } + + return $template; + } + + /** + * fills a template with values + * + * @static + * @param string $template Template to be used + * @param array $values Array of all the values + * @return string string filled with tag contents + */ + static public function fill($template, $values) + { + + if ( sizeof($values) != 0 ) + { + foreach ( $values as $key => $value ) + { + $template = preg_replace('#<%' . preg_quote($key, '#') . '%>#', $value, $template); + } + } + + // remove non matched template-tags + return preg_replace('#<%([a-zA-Z]+)?%>#', '', $template); + } + + /** + * TEMPLATE::exists() + * returns true if there is a template with the given shortname + * + * @static + * @param string $name template name + * @return boolean exists or not + */ + static public function exists($name) + { + $query = "SELECT * FROM %s WHERE tdname=%s"; + $query = sprintf($query, sql_table('template_desc'), DB::quoteValue($name)); + $r = DB::getResult($query); + return ($r->rowCount() != 0); + } + + /** + * TEMPLATE::existsID() + * returns true if there is a template with the given ID + * + * @static + * @param integer $id id for template + * @return bookean exists or not + */ + static public function existsID($id) + { + $query = "SELECT * FROM %s WHERE tdnumber=%d"; + $query = sprintf($query, sql_table('template_desc'), (integer) $id); + $r = DB::getResult($query); + return ($r->rowCount() != 0); + } + + /** + * TEMPLATE::getNameFromId() + * + * @static + * @param integer $id id for template + * @return object sql object + */ + static public function getNameFromId($id) + { + $query = "SELECT tdname as result FROM %s WHERE tdnumber=%d"; + $query = sprintf($query, sql_table('template_desc'), (integer) $id); + return DB::getValue($query); + } + + /** + * TEMPLATE::getDesc() + * + * @static + * @param integer $id id for template + * @return string description for the template + */ + static public function getDesc($id) + { + $query = "SELECT tddesc FROM %s WHERE tdnumber=%d"; + $query = sprintf($query, sql_table('template_desc'), (integer) $id); + return DB::getValue($query); + } +} ++======= + id = intval($templateid); + return; + } + + /** + * Template::getID() + * + * @param void + * @return integer id for this instance of Template class + */ + public function getID() + { + return (integer) $this->id; + } + + /** + * Template::createFromName() + * + * @statc + * @param string $name template name + * @return object instance of Template class generated by the name + */ + static public function createFromName($name) + { + return new Template(Template::getIdFromName($name)); + } + + /** + * Template::getIdFromName() + * + * @static + * @param string $name template name + * @return integer id for the template + */ + static public function getIdFromName($name) + { + $name = DB::quoteValue($name); + $query = "SELECT tdnumber FROM %s WHERE tdname=%s"; + $query = sprintf($query, sql_table('template_desc'), $name); + return DB::getValue($query); + } + + /** + * Template::updateGeneralInfo() + * Updates the general information about the template + * + * @param string $name template name + * @param string $desc description for this template + * @return void + */ + public function updateGeneralInfo($name, $desc) + { + $query = "UPDATE %s SET tdname=%s, tddesc=%s WHERE tdnumber=%d"; + $query = sprintf($query, sql_table('template_desc'), DB::quoteValue($name), DB::quoteValue($desc), (integer) $this->getID()); + DB::execute($query); + return; + } + + /** + * Template::update() + * Updates the contents of one part of the template + * + * @param String $type value for nucleus_template.tpartname + * @param String $content value for nucleus_template.tcontent + * @return Void + */ + public function update($type, $content) + { + // delete old thingie + $query = "DELETE FROM %s WHERE tpartname=%s and tdesc=%d"; + $query = sprintf($query, sql_table('template'), DB::quoteValue($type), (integer) $this->getID()); + DB::execute($query); + + // write new thingie + if ( $content ) + { + $query = "INSERT INTO %s (tcontent, tpartname, tdesc) VALUES (%s, %s, %d)"; + $query = sprintf($query, sql_table('template'), DB::quoteValue($content), DB::quoteValue($type), (integer) $this->getID()); + DB::execute($query); + } + return; + } + + /** + * Template::deleteAllParts() + * Deletes all template parts from the database + * + * @param void + * @return void + */ + public function deleteAllParts() + { + $query = "DELETE FROM %s WHERE tdesc=%d"; + $query = sprintf($query, sql_table('template'), (integer) $this->getID()); + DB::execute($query); + return; + } + + /** + * Template::createNew() + * Creates a new template + * + * @static + * @param string $name name for new template + * @param string $desc description for new template + * @return integer id for new template + */ + static public function createNew($name, $desc) + { + global $manager; + + $data = array( + 'name' => &$name, + 'description' => &$desc + ); + $manager->notify('PreAddTemplate', $data); + + DB::execute('INSERT INTO '.sql_table('template_desc').' (tdname, tddesc) VALUES (' . DB::quoteValue($name) . ',' . DB::quoteValue($desc) . ')'); + $newId = DB::getInsertId(); + + $data = array( + 'templateid' => $newId, + 'name' => $name, + 'description' => $desc + ); + $manager->notify('PostAddTemplate', $data); + + return $newId; + } + + /** + * Reads a template and returns an array with the parts. + * + * @static + * @param string $name name of the template file + * @return array template array + */ + static public function read($name) + { + global $manager; + $data = array('template' => &$name); + $manager->notify('PreTemplateRead', $data); + + $query = "SELECT tpartname, tcontent FROM %s, %s WHERE tdesc=tdnumber and tdname=%s"; + $query = sprintf($query, sql_table('template_desc'), sql_table('template'), DB::quoteValue($name)); + $res = DB::getResult($query); + + $template = array(); + foreach ( $res as $row ) + { + $template[$row['tpartname']] = $row['tcontent']; + } + + return $template; + } + + /** + * fills a template with values + * + * @static + * @param string $template Template to be used + * @param array $values Array of all the values + * @return string string filled with tag contents + */ + static public function fill($template, $values) + { + + if ( sizeof($values) != 0 ) + { + foreach ( $values as $key => $value ) + { + $template = preg_replace('#<%' . preg_quote($key, '#') . '%>#', $value, $template); + } + } + + // remove non matched template-tags + return preg_replace('#<%([a-zA-Z]+)?%>#', '', $template); + } + + /** + * Template::exists() + * returns true if there is a template with the given shortname + * + * @static + * @param string $name template name + * @return boolean exists or not + */ + static public function exists($name) + { + $query = "SELECT * FROM %s WHERE tdname=%s"; + $query = sprintf($query, sql_table('template_desc'), DB::quoteValue($name)); + $r = DB::getResult($query); + return ($r->rowCount() != 0); + } + + /** + * Template::existsID() + * returns true if there is a template with the given ID + * + * @static + * @param integer $id id for template + * @return bookean exists or not + */ + static public function existsID($id) + { + $query = "SELECT * FROM %s WHERE tdnumber=%d"; + $query = sprintf($query, sql_table('template_desc'), (integer) $id); + $r = DB::getResult($query); + return ($r->rowCount() != 0); + } + + /** + * Template::getNameFromId() + * + * @static + * @param integer $id id for template + * @return object sql object + */ + static public function getNameFromId($id) + { + $query = "SELECT tdname as result FROM %s WHERE tdnumber=%d"; + $query = sprintf($query, sql_table('template_desc'), (integer) $id); + return DB::getValue($query); + } + + /** + * Template::getDesc() + * + * @static + * @param integer $id id for template + * @return string description for the template + */ + static public function getDesc($id) + { + $query = "SELECT tddesc FROM %s WHERE tdnumber=%d"; + $query = sprintf($query, sql_table('template_desc'), (integer) $id); + return DB::getValue($query); + } + } ++>>>>>>> skinnable-master diff --combined nucleus/libs/backup.php index 64ae2da,dcc5d71..ecc4762 --- a/nucleus/libs/backup.php +++ b/nucleus/libs/backup.php @@@ -1,432 -1,433 +1,867 @@@ ++<<<<<<< HEAD +getPlugin($row['pfile']); + if ( $plug ) + { + $tables = array_merge($tables, (array) $plug->getTableList()); + } + } + ob_end_clean(); + + // remove duplicates + $tables = array_unique($tables); + + // make sure browsers don't cache the backup + header("Pragma: no-cache"); + + // don't allow gzip compression when extension is not loaded + if ( ($gzip != 0) && !extension_loaded("zlib") ) + { + $gzip = 0; + } + + if ( !$gzip ) + { + $filename = 'nucleus_db_backup_' . i18n::formatted_datetime('%Y-%m-%d-%H-%M-%S', time()) . ".sql"; + } + else + { + // use an output buffer + @ob_start(); + @ob_implicit_flush(0); + + // set filename + $filename = 'nucleus_db_backup_' . i18n::formatted_datetime('%Y-%m-%d-%H-%M-%S', time()) . ".sql.gz"; + } + + // send headers that tell the browser a file is coming + header("Content-Type: text/x-delimtext; name=\"$filename\""); + header("Content-disposition: attachment; filename=$filename"); + + // dump header + echo "/*\n"; + echo " * This is a backup file generated by Nucleus \n"; + echo " * http://www.nucleuscms.org/\n"; + echo " * \n"; + echo " * backup-date: " . i18n::formatted_datetime('rfc822GMT', time()) . "\n"; + echo " * Nucleus CMS version: " . $nucleus['version'] . "\n"; + echo " * \n"; + echo " * WARNING: Only try to restore on servers running the exact same version of Nucleus\n"; + echo " */\n"; + + // dump all tables + reset($tables); + array_walk($tables, array(__CLASS__, 'dump_table')); + + if ( $gzip ) + { + $Size = ob_get_length(); + $Crc = crc32(ob_get_contents()); + $contents = gzcompress(ob_get_contents()); + ob_end_clean(); + echo "\x1f\x8b\x08\x00\x00\x00\x00\x00" . substr($contents, 0, strlen($contents) - 4) + . self::gzip_print_four_characters($Crc) . self::gzip_print_four_characters($Size); + } + exit; + } + + /** + * Backup::dump_table() + * Creates a dump for a single table + * ($tablename and $key are filled in by array_walk) + * + * @static + * @param string $tablename + * @param string $key + */ + static private function dump_table($tablename, $key) + { + echo "/*\n"; + echo " * TABLE: " . $tablename . "\n"; + echo " */\n"; + + // dump table structure + self::dump_structure($tablename); + + // dump table contents + self::dump_contents($tablename); + return; + } + + /** + * Backup::dump_structure() + * Creates a dump of the table structure for one table + * + * @static + * @param string $tablename + * @return void + * + */ + static private function dump_structure($tablename) + { + // add command to drop table on restore + echo "DROP TABLE IF EXISTS {$tablename};\n\n"; + $result = DB::getRow("SHOW CREATE TABLE {$tablename}"); + echo $result['Create Table']; + echo ";\n\n"; + return; + } + + /** + * Backup::get_field_names() + * Returns the field named for the given table in the + * following format: + * (column1, column2, ..., columnn) + * + * @static + * @param resource $result + * @param integer $num_fields + * @return string + */ + static private function get_field_names($result, $num_fields) + { + $fields = array(); + for ( $j = 0; $j < $num_fields; $j++ ) + { + $col = $result->getColumnMeta($j); + $fields[] = $col['name']; + } + + return '(' . implode(', ', $fields) . ')'; + } + + /** + * Backup::dump_contents() + * Creates a dump of the table content for one table + * + * @static + * @param string $tablename + * @return void + * + */ + static private function dump_contents($tablename) + { + /* + * Grab the data from the table. + */ + $result = DB::getResult("SELECT * FROM $tablename"); + + if ( $result->rowCount() > 0 ) + { + echo "\n"; + echo "/*\n"; + echo " * Table Data for {$tablename}\n"; + echo " */\n"; + } + + $num_fields = $result->columnCount(); + + /* + * Compose fieldname list + */ + $tablename_list = self::get_field_names($result, $num_fields); + + /* + * Loop through the resulting rows and build the sql statement. + */ + foreach ( $result as $row ) + { + // Start building the SQL statement. + echo 'INSERT INTO ' . $tablename . ' ' . $tablename_list . ' VALUES('; + + // Loop through the rows and fill in data for each column + for ( $j = 0; $j < $num_fields; $j++ ) + { + if ( !isset($row[$j]) ) + { + // no data for column + echo ' NULL'; + } + elseif ( $row[$j] != '' ) + { + // data + echo ' ' . DB::quoteValue($row[$j]); + } + else + { + // empty column (!= no data!) + echo "''"; + } + + // only add comma when not last column + if ( $j != ($num_fields - 1) ) + { + echo ','; + } + } + echo ");\n"; + } + echo "\n"; + return; + } + + /** + * Backup::gzip_print_four_characters() + * + * @static + * @param integer $val + * @return integer + */ + static private function gzip_print_four_characters($Val) + { + for ( $i = 0; $i < 4; $i ++ ) + { + $return .= chr($Val % 256); + $Val = floor($Val / 256); + } + return $return; + } + + /** + * Backup::do_restore() + * Restores a database backup + * + * NOTE: this remains not-static for compatibility + * + * @param void + * @return void + */ + public function do_restore() + { + $uploadInfo = postFileInfo('backup_file'); + + // first of all: get uploaded file: + if ( array_key_exists('name', $uploadInfo) && empty($uploadInfo['name']) ) + { + return 'No file uploaded'; + } + if ( !is_uploaded_file($uploadInfo['tmp_name']) ) + { + return 'No file uploaded'; + } + + $backup_file_name = $uploadInfo['name']; + $backup_file_tmpname = $uploadInfo['tmp_name']; + $backup_file_type = $uploadInfo['type']; + + if ( !file_exists($backup_file_tmpname) ) + { + return 'File Upload Error'; + } + + if ( !preg_match("#^(text/[a-zA-Z]+)|(application/(x\-)?gzip(\-compressed)?)|(application/octet-stream)$#i", $backup_file_type) ) + { + return 'The uploaded file is not of the correct type'; + } + + $gzip = 0; + if ( preg_match("#\.gz#i", $backup_file_name) ) + { + $gzip = 1; + } + + if ( !extension_loaded("zlib") && $gzip ) + { + return 'Cannot decompress gzipped backup (zlib package not installed)'; + } + + // get sql query according to gzip setting (either decompress, or not) + $contents = self::get_contents($backup_file_tmpname, $gzip); + if ( $contents == '' ) + { + return 'Cannot get contents from this file.'; + } + + /* detect lines */ + $lines = preg_split('/[\r\n]/', $contents); + if( $lines === $contents ) + { + return 'Cannot parse contents from this file'; + } + + /* get sql statements from each lines */ + $queries = self::get_queries($lines); + if ( $queries === array() ) + { + return "Cannot get SQL queries from this file."; + } + + /* execute sql statements */ + foreach ( $queries as $query ) + { + if ( DB::execute($query) === FALSE ) + { + $error = DB::getError(); + debug('SQL Error: ' . $error[2]); + break; + } + continue; + } + return; + } + + static private function get_contents($temporary_name, $gzip = 0) + { + $contents = ''; + if ( $gzip ) + { + // decompress and read + $gz_ptr = gzopen($temporary_name, 'rb'); + while ( !gzeof($gz_ptr) ) + { + $contents .= gzgets($gz_ptr, 100000); + } + } + else + { + // just read + $fsize = filesize($temporary_name); + if ( $fsize > 0 ) + { + $contents = fread(fopen($temporary_name, 'r'), $fsize); + } + } + return $contents; + } + + static private function get_queries($lines) + { + $query = ''; + $queries = array(); + foreach ( $lines as $line ) + { + $line = trim($line); + if ( !$line || $line[0] == '#' || preg_match('#^[\s|/]?\*#', $line) ) + { + continue; + } + + if ( preg_match('/^(.*);$/', $line, $matches) === 0 ) + { + $query .= $line; + } + else + { + $query .= $matches[1]; + $queries[] = $query; + $query = ''; + } + continue; + } + return $queries; + } ++======= + getPlugin($row['pfile']); + if ( $plug ) + { + $tables = array_merge($tables, (array) $plug->getTableList()); + } + } + ob_end_clean(); + + // remove duplicates + $tables = array_unique($tables); + + // make sure browsers don't cache the backup + header("Pragma: no-cache"); + + // don't allow gzip compression when extension is not loaded + if ( ($gzip != 0) && !extension_loaded("zlib") ) + { + $gzip = 0; + } + + if ( !$gzip ) + { + $filename = 'nucleus_db_backup_' . i18n::formatted_datetime('%Y-%m-%d-%H-%M-%S', time()) . ".sql"; + } + else + { + // use an output buffer + @ob_start(); + @ob_implicit_flush(0); + + // set filename + $filename = 'nucleus_db_backup_' . i18n::formatted_datetime('%Y-%m-%d-%H-%M-%S', time()) . ".sql.gz"; + } + + // send headers that tell the browser a file is coming + header("Content-Type: text/x-delimtext; name=\"$filename\""); + header("Content-disposition: attachment; filename=$filename"); + + // dump header + echo "/*\n"; + echo " * This is a backup file generated by Nucleus \n"; + echo " * http://www.nucleuscms.org/\n"; + echo " * \n"; + echo " * backup-date: " . i18n::formatted_datetime('rfc822GMT', time()) . "\n"; + echo " * Nucleus CMS version: " . $nucleus['version'] . "\n"; + echo " * \n"; + echo " * WARNING: Only try to restore on servers running the exact same version of Nucleus\n"; + echo " */\n"; + + // dump all tables + reset($tables); + /* NOTE: hope to use 'self' keyword here but works bad so here use __CLASS__ macro. */ + array_walk($tables, array(__CLASS__, 'dump_table')); + + if ( $gzip ) + { + $Size = ob_get_length(); + $Crc = crc32(ob_get_contents()); + $contents = gzcompress(ob_get_contents()); + ob_end_clean(); + echo "\x1f\x8b\x08\x00\x00\x00\x00\x00" . substr($contents, 0, strlen($contents) - 4) + . self::gzip_print_four_characters($Crc) . self::gzip_print_four_characters($Size); + } + exit; + } + + /** + * Backup::dump_table() + * Creates a dump for a single table + * ($tablename and $key are filled in by array_walk) + * + * @static + * @param string $tablename + * @param string $key + */ + static private function dump_table($tablename, $key) + { + echo "/*\n"; + echo " * TABLE: " . $tablename . "\n"; + echo " */\n"; + + // dump table structure + self::dump_structure($tablename); + + // dump table contents + self::dump_contents($tablename); + return; + } + + /** + * Backup::dump_structure() + * Creates a dump of the table structure for one table + * + * @static + * @param string $tablename + * @return void + * + */ + static private function dump_structure($tablename) + { + // add command to drop table on restore + echo "DROP TABLE IF EXISTS {$tablename};\n\n"; + $result = DB::getRow("SHOW CREATE TABLE {$tablename}"); + echo $result['Create Table']; + echo ";\n\n"; + return; + } + + /** + * Backup::get_field_names() + * Returns the field named for the given table in the + * following format: + * (column1, column2, ..., columnn) + * + * @static + * @param resource $result + * @param integer $num_fields + * @return string + */ + static private function get_field_names($result, $num_fields) + { + $fields = array(); + for ( $j = 0; $j < $num_fields; $j++ ) + { + $col = $result->getColumnMeta($j); + $fields[] = $col['name']; + } + + return '(' . implode(', ', $fields) . ')'; + } + + /** + * Backup::dump_contents() + * Creates a dump of the table content for one table + * + * @static + * @param string $tablename + * @return void + * + */ + static private function dump_contents($tablename) + { + /* + * Grab the data from the table. + */ + $result = DB::getResult("SELECT * FROM $tablename"); + + if ( $result->rowCount() > 0 ) + { + echo "\n"; + echo "/*\n"; + echo " * Table Data for {$tablename}\n"; + echo " */\n"; + } + + $num_fields = $result->columnCount(); + + /* + * Compose fieldname list + */ + $tablename_list = self::get_field_names($result, $num_fields); + + /* + * Loop through the resulting rows and build the sql statement. + */ + foreach ( $result as $row ) + { + // Start building the SQL statement. + echo 'INSERT INTO ' . $tablename . ' ' . $tablename_list . ' VALUES('; + + // Loop through the rows and fill in data for each column + for ( $j = 0; $j < $num_fields; $j++ ) + { + if ( !isset($row[$j]) ) + { + // no data for column + echo ' NULL'; + } + elseif ( $row[$j] != '' ) + { + // data + echo ' ' . DB::quoteValue($row[$j]); + } + else + { + // empty column (!= no data!) + echo "''"; + } + + // only add comma when not last column + if ( $j != ($num_fields - 1) ) + { + echo ','; + } + } + echo ");\n"; + } + echo "\n"; + return; + } + + /** + * Backup::gzip_print_four_characters() + * + * @static + * @param integer $val + * @return integer + */ + static private function gzip_print_four_characters($Val) + { + for ( $i = 0; $i < 4; $i ++ ) + { + $return .= chr($Val % 256); + $Val = floor($Val / 256); + } + return $return; + } + + /** + * Backup::do_restore() + * Restores a database backup + * + * NOTE: this remains not-static for compatibility + * + * @param void + * @return void + */ + public function do_restore() + { + $uploadInfo = postFileInfo('backup_file'); + + // first of all: get uploaded file: + if ( array_key_exists('name', $uploadInfo) && empty($uploadInfo['name']) ) + { + return 'No file uploaded'; + } + if ( !is_uploaded_file($uploadInfo['tmp_name']) ) + { + return 'No file uploaded'; + } + + $backup_file_name = $uploadInfo['name']; + $backup_file_tmpname = $uploadInfo['tmp_name']; + $backup_file_type = $uploadInfo['type']; + + if ( !file_exists($backup_file_tmpname) ) + { + return 'File Upload Error'; + } + + if ( !preg_match("#^(text/[a-zA-Z]+)|(application/(x\-)?gzip(\-compressed)?)|(application/octet-stream)$#i", $backup_file_type) ) + { + return 'The uploaded file is not of the correct type'; + } + + $gzip = 0; + if ( preg_match("#\.gz#i", $backup_file_name) ) + { + $gzip = 1; + } + + if ( !extension_loaded("zlib") && $gzip ) + { + return 'Cannot decompress gzipped backup (zlib package not installed)'; + } + + // get sql query according to gzip setting (either decompress, or not) + $contents = self::get_contents($backup_file_tmpname, $gzip); + if ( $contents == '' ) + { + return 'Cannot get contents from this file.'; + } + + /* detect lines */ + $lines = preg_split('/[\r\n]/', $contents); + if( $lines === $contents ) + { + return 'Cannot parse contents from this file'; + } + + /* get sql statements from each lines */ + $queries = self::get_queries($lines); + if ( $queries === array() ) + { + return "Cannot get SQL queries from this file."; + } + + /* execute sql statements */ + foreach ( $queries as $query ) + { + if ( DB::execute($query) === FALSE ) + { + $error = DB::getError(); + debug('SQL Error: ' . $error[2]); + break; + } + continue; + } + return; + } + + static private function get_contents($temporary_name, $gzip = 0) + { + $contents = ''; + if ( $gzip ) + { + // decompress and read + $gz_ptr = gzopen($temporary_name, 'rb'); + while ( !gzeof($gz_ptr) ) + { + $contents .= gzgets($gz_ptr, 100000); + } + } + else + { + // just read + $fsize = filesize($temporary_name); + if ( $fsize > 0 ) + { + $contents = fread(fopen($temporary_name, 'r'), $fsize); + } + } + return $contents; + } + + static private function get_queries($lines) + { + $query = ''; + $queries = array(); + foreach ( $lines as $line ) + { + $line = trim($line); + if ( !$line || $line[0] == '#' || preg_match('#^[\s|/]?\*#', $line) ) + { + continue; + } + + if ( preg_match('/^(.*);$/', $line, $matches) === 0 ) + { + $query .= $line; + } + else + { + $query .= $matches[1]; + $queries[] = $query; + $query = ''; + } + continue; + } + return $queries; + } ++>>>>>>> skinnable-master } diff --combined nucleus/libs/globalfunctions.php index 9a7688a,2c443f6..e6448a8 --- a/nucleus/libs/globalfunctions.php +++ b/nucleus/libs/globalfunctions.php @@@ -1,1809 -1,1839 +1,3648 @@@ ++<<<<<<< HEAD + 0 ) +{ + $nucleus['version'] .= '/' . getNucleusPatchLevel(); +} + +/* Avoid notices */ +if ( !array_key_exists('installscript', $CONF) || empty($CONF['installscript']) ) +{ + $CONF['installscript'] = 0; +} +if ( !array_key_exists('UsingAdminArea', $CONF) ) +{ + $CONF['UsingAdminArea'] = 0; +} + +if ( !headers_sent() ) +{ + header('Generator: Nucleus CMS ' . $nucleus['version']); +} + + +/* TODO: This is for compatibility since 4.0, should be obsoleted at future release. */ +if ( !isset($DIR_LOCALES) ) +{ + $DIR_LOCALES = $DIR_NUCLEUS . 'locales/'; +} +global $DIR_LANG; +if ( !isset($DIR_LANG) ) +{ + $DIR_LANG = $DIR_LOCALES; +} + +/* load and initialize i18n class */ +if (!class_exists('i18n', FALSE)) +{ + include($DIR_LIBS . 'i18n.php'); +} +if ( !i18n::init('UTF-8', $DIR_LOCALES) ) +{ + exit('Fail to initialize i18n class.'); +} + +/* TODO: This is just for compatibility since 4.0, should be obsoleted at future release. */ +define('_CHARSET', i18n::get_current_charset()); + + +/* + * NOTE: Since 4.0 release, Entity class becomes to be important class + * with some wrapper functions for htmlspechalchars/htmlentity PHP's built-in function + */ +include($DIR_LIBS . 'ENTITY.php'); + +/* we will use postVar, getVar, ... methods instead of $_GET, $_POST ... */ +if ( $CONF['installscript'] != 1 ) +{ + /* vars were already included in install.php */ + include_once($DIR_LIBS . 'vars4.1.0.php'); + + /* added for 4.0 DB::* wrapper and compatibility sql_* */ + include_once($DIR_LIBS . 'sql/sql.php'); +} + +/* include core classes that are needed for login & plugin handling */ +include($DIR_LIBS . 'MEMBER.php'); +include($DIR_LIBS . 'ACTIONLOG.php'); +include($DIR_LIBS . 'MANAGER.php'); +include($DIR_LIBS . 'PLUGIN.php'); + +$manager =& MANAGER::instance(); + +/* only needed when updating logs */ +if ( $CONF['UsingAdminArea'] ) +{ + /* XML-RPC client classes */ + include($DIR_LIBS . 'xmlrpc.inc.php'); + include($DIR_LIBS . 'ADMIN.php'); +} + + +/* connect to database */ +if ( !isset($MYSQL_HANDLER) ) +{ + $MYSQL_HANDLER = array('mysql',''); +} +if ( $MYSQL_HANDLER[0] == '' ) +{ + $MYSQL_HANDLER[0] = 'mysql'; +} +DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE); + + +/* force locale or charset */ +$locale = ''; +$charset = i18n::get_current_charset(); + +$data = array( + 'locale' => &$locale, + 'charset' => &$charset +); +$manager->notify('ForceLocale', $data); + +if ( $data['locale'] !== '' ) +{ + i18n::set_forced_locale($data['locale']); +} +if ( $data['charset'] !== '' ) +{ + i18n::set_forced_charset($data['charset']); +} +unset($locale); +unset($charset); + + +/* convert forced charset to current charset */ +if ( i18n::get_forced_charset() != i18n::get_current_charset() ) +{ + $_POST = i18n::convert_array($_POST, i18n::get_forced_charset()); + $_GET = i18n::convert_array($_GET, i18n::get_forced_charset()); + $_REQUEST = i18n::convert_array($_REQUEST, i18n::get_forced_charset()); + $_COOKIE = i18n::convert_array($_COOKIE, i18n::get_forced_charset()); + $_FILES = i18n::convert_array($_FILES, i18n::get_forced_charset()); + + if ( session_id() !== '' ) + { + $_SESSION = i18n::convert_array($_SESSION, i18n::get_forced_charset()); + } +} + + +/* sanitize option */ +$bLoggingSanitizedResult = 0; +$bSanitizeAndContinue = 0; +$orgRequestURI = serverVar('REQUEST_URI'); +sanitizeParams(); + +/* logs sanitized result if need */ +if ( $orgRequestURI !== serverVar('REQUEST_URI') ) +{ + $msg = "Sanitized [" . serverVar('REMOTE_ADDR') . "] "; + $msg .= $orgRequestURI . " -> " . serverVar('REQUEST_URI'); + if ( $bLoggingSanitizedResult ) + { + addToLog(WARNING, $msg); + } + if ( !$bSanitizeAndContinue ) + { + die(""); + } +} + +/* get all variables that can come from the request and put them in the global scope */ +$blogid = requestVar('blogid'); +$itemid = intRequestVar('itemid'); +$catid = intRequestVar('catid'); +$skinid = requestVar('skinid'); +$memberid = requestVar('memberid'); +$archivelist = requestVar('archivelist'); +$imagepopup = requestVar('imagepopup'); +$archive = requestVar('archive'); +$query = requestVar('query'); +$highlight = requestVar('highlight'); +$amount = requestVar('amount'); +$action = requestVar('action'); +$nextaction = requestVar('nextaction'); +$maxresults = requestVar('maxresults'); +$startpos = intRequestVar('startpos'); +$errormessage = ''; +$error = ''; +$special = requestVar('special'); + + +/* read config */ +getConfig(); + + +/* Properly set $CONF['Self'] and others if it's not set... + * usually when we are access from admin menu + */ +if ( !array_key_exists('Self', $CONF) ) +{ + $CONF['Self'] = $CONF['IndexURL']; + /* strip trailing */ + if ( $CONF['Self'][i18n::strlen($CONF['Self']) -1] == "/" ) + { + $CONF['Self'] = i18n::substr($CONF['Self'], 0, i18n::strlen($CONF['Self']) -1); + } +} + +$CONF['ItemURL'] = $CONF['Self']; +$CONF['ArchiveURL'] = $CONF['Self']; +$CONF['ArchiveListURL'] = $CONF['Self']; +$CONF['MemberURL'] = $CONF['Self']; +$CONF['SearchURL'] = $CONF['Self']; +$CONF['BlogURL'] = $CONF['Self']; +$CONF['CategoryURL'] = $CONF['Self']; + +/* automatically use simpler toolbar for mozilla */ +if ( ($CONF['DisableJsTools'] == 0) + && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Mozilla/5.0') !== FALSE + && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Gecko') !== FALSE ) +{ + $CONF['DisableJsTools'] = 2; +} + +/* login processing */ +$member = new Member(); + +if ( $action == 'login' ) +{ + $login = postVar('login'); + $password = postVar('password'); + $shared = intPostVar('shared'); + $member->login($login, $password, $shared); +} +elseif ( ($action == 'logout') ) +{ + $member->logout(); +} +else +{ + $member->cookielogin(); +} + + +/* TODO: This is for backward compatibility, should be obsoleted near future. */ +if ( !preg_match('#^(.+)_(.+)_(.+)$#', $CONF['Locale']) + && ($CONF['Locale'] = i18n::convert_old_language_file_name_to_locale($CONF['Locale'])) === FALSE ) +{ + $CONF['Locale'] = 'en_Latn_US'; +} +if ( !array_key_exists('Language', $CONF) ) +{ + $CONF['Language'] = i18n::convert_locale_to_old_language_file_name($CONF['Locale']); +} +$locale = $CONF['Locale']; + + +/* NOTE: include translation file and set locale */ +if ( $member->isLoggedIn() ) +{ + if ( $member->getLocale() ) + { + $locale = $member->getLocale(); + } +} +else +{ + if ( i18n::get_forced_locale() !== '' ) + { + $locale = i18n::get_forced_locale(); + } +} +include_translation($locale); +i18n::set_current_locale($locale); + + +/* login completed */ +$manager->notify('PostAuthentication', array('loggedIn' => $member->isLoggedIn() ) ); + +/* next action */ +if ( $member->isLoggedIn() && $nextaction ) +{ + $action = $nextaction; +} + +/* first, let's see if the site is disabled or not. always allow admin area access. */ +if ( $CONF['DisableSite'] && !$member->isAdmin() && !$CONF['UsingAdminArea'] ) +{ + redirect($CONF['DisableSiteURL']); + exit; +} + +/* load other classes */ +include($DIR_LIBS . 'PARSER.php'); +include($DIR_LIBS . 'SKIN.php'); +include($DIR_LIBS . 'TEMPLATE.php'); +include($DIR_LIBS . 'BLOG.php'); +include($DIR_LIBS . 'BODYACTIONS.php'); +include($DIR_LIBS . 'COMMENTS.php'); +include($DIR_LIBS . 'COMMENT.php'); +include($DIR_LIBS . 'NOTIFICATION.php'); +include($DIR_LIBS . 'BAN.php'); +include($DIR_LIBS . 'PAGEFACTORY.php'); +include($DIR_LIBS . 'SEARCH.php'); +include($DIR_LIBS . 'LINK.php'); + +/* set lastVisit cookie (if allowed) */ +if ( !headers_sent() ) +{ + if ( $CONF['LastVisit'] ) + { + setcookie($CONF['CookiePrefix'] . 'lastVisit', time(), time() + 2592000, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + } + else + { + setcookie($CONF['CookiePrefix'] . 'lastVisit', '', (time() - 2592000), $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + } +} + +if ( !defined('_ARCHIVETYPE_MONTH') ) +{ + define('_ARCHIVETYPE_DAY', 'day'); + define('_ARCHIVETYPE_MONTH', 'month'); + define('_ARCHIVETYPE_YEAR', 'year'); +} + +/* for path resolving */ +$virtualpath = getVar('virtualpath'); +if ( getVar('virtualpath') == '' ) + { + $virtualpath = serverVar('PATH_INFO'); + } + +/* + * switch URLMode back to normal when $CONF['Self'] ends in .php + * this avoids urls like index.php/item/13/index.php/item/15 + */ +if ( !array_key_exists('URLMode', $CONF) || ($CONF['URLMode'] != 'pathinfo') ) + { + $CONF['URLMode'] = 'normal'; + } +else + { + if ( i18n::substr($CONF['Self'], i18n::strlen($CONF['Self']) - 4) != '.php' ) + { + decodePathInfo($virtualpath); + } +} + +/* + * PostParseURL is a place to cleanup any of the path-related global variables before the selector function is run. + * It has 2 values in the data in case the original virtualpath is needed, but most the use will be in tweaking + * global variables to clean up (scrub out catid or add catid) or to set someother global variable based on + * the values of something like catid or itemid + * New in 3.60 + */ +$data = array( + 'type' => basename(serverVar('SCRIPT_NAME')), + 'info' => $virtualpath +); +$manager->notify('PostParseURL', $data); + +/* + * NOTE: Here is the end of initialization + */ + +/** + * include_libs() + * This function includes or requires the specified library file + * + * @param string $file + * @param boolean $once use the _once() version + * @param boolean $require use require() instead of include() + * @return void + */ +function include_libs($file, $once = TRUE, $require = TRUE) +{ + global $DIR_LIBS; + + // $DIR_LIBS isn't a directory + if ( !is_dir($DIR_LIBS) ) + { + exit; + } + + $lib_path = $DIR_LIBS . $file; + + if ( $once && $require ) + { + require_once($lib_path); + } + else if ( $once && !$require ) + { + include_once($lib_path); + } + else if ( $require ) + { + require($lib_path); + } + else + { + include($lib_path); + } + return; +} + +/** + * include_plugins() + * This function includes or requires the specified plugin file + * + * @param string $file + * @param boolean $once use the _once() version + * @param boolean $require use require() instead of include() + * @return + */ +function include_plugins($file, $once = TRUE, $require = TRUE) +{ + global $DIR_PLUGINS; + + // begin if: $DIR_LIBS isn't a directory + if ( !is_dir($DIR_PLUGINS) ) + { + exit; + } + + $plugin_path = $DIR_PLUGINS . $file; + + // begin if: + if ( $once && $require ) + { + require_once($plugin_path); + } + else if ( $once && !$require ) + { + include_once($plugin_path); + } + elseif ( $require ) + { + require($plugin_path); + } + else + { + include($plugin_path); + } + return; +} + +/** + * include_translation() + * This function decide which locale is used and include translation + * + * @param string &$locale locale name referring to 'language tags' defined in RFC 5646 + * @return void + */ +function include_translation(&$locale) +{ + global $DIR_LOCALES; + + $translation_file = $DIR_LOCALES . $locale . '.' . i18n::get_current_charset() . '.php'; + if ( !file_exists($translation_file) ) + { + $locale = 'en_Latn_US'; + $translation_file = $DIR_LOCALES . 'en_Latn_US.ISO-8859-1.php'; + } + include($translation_file); + return; +} + +/** + * intPostVar() + * This function returns the integer value of $_POST for the variable $name + * + * @param string $name field to get the integer value of + * @return integer + */ +function intPostVar($name) +{ + return (integer) postVar($name); +} + + +/** + * intGetVar() + * This function returns the integer value of $_GET for the variable $name + * + * @param string $name field to get the integer value of + * @return integer + */ +function intGetVar($name) +{ + return (integer) getVar($name); +} + + +/** + * intRequestVar() + * This function returns the integer value of $_REQUEST for the variable $name. Also checks $_GET and $_POST if not found in $_REQUEST + * + * @param string $name field to get the integer value of + * @return int + */ +function intRequestVar($name) +{ + return (integer) requestVar($name); +} + + +/** + * intCookieVar() + * This function returns the integer value of $_COOKIE for the variable $name + * + * @param string $name field to get the integer value of + * @return integer + */ +function intCookieVar($name) +{ + return (integer) cookieVar($name); +} + +/** + * getNucleusVersion() + * This function returns the current Nucleus version (100 = 1.00, 101 = 1.01, etc...) + * + * @param void + * @return integer + */ +function getNucleusVersion() +{ + return 400; +} + +/** + * getNucleusPatchLevel() + * TODO: Better description of this function. + * + * Power users can install patches in between nucleus releases. These patches + * usually add new functionality in the plugin API and allow those to + * be tested without having to install CVS. + * + *@param void + * @return integer + */ +function getNucleusPatchLevel() +{ + return 0; +} + +/** + * getLatestVersion() + * This function returns the latest Nucleus version available for download from nucleuscms.org or FALSE if unable to attain data + * Format will be major.minor/patachlevel e.g. 3.41 or 3.41/02 + * + * @param void + * @return mixed + */ +function getLatestVersion() +{ + // begin if: cURL is not available in this PHP installation + if ( !function_exists('curl_init') ) + { + return FALSE; + } + + $curl = curl_init(); + $timeout = 5; + + curl_setopt ($curl, CURLOPT_URL, 'http://nucleuscms.org/version_check.php'); + curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout); + + $return = curl_exec($curl); + + curl_close($curl); + + return $return; +} + +/** + * sql_table() + * This function returns a Nucleus table name with the appropriate prefix + * @param string $name + * @return string + */ +function sql_table($name) +{ + global $MYSQL_PREFIX; + + // begin if: no MySQL prefix + if ( empty($MYSQL_PREFIX) ) + { + return 'nucleus_' . $name; + } + // else: use MySQL prefix + else + { + return $MYSQL_PREFIX . 'nucleus_' . $name; + } + return; +} + +/** + * sendContentType() + * This function sends the Content-Type header if headers have not already been sent + * It also determines if the browser can accept application/xhtml+xml and sends it only to those that can. + * + * if content type is application/xhtml+xml, only send it to browsers + * that can handle it (IE6 cannot). Otherwise, send text/html + * + * v2.5: + * For admin area pages, keep sending text/html (unless it's a debug version) + * application/xhtml+xml still causes too much problems with the javascript implementations + * + * v3.3: + * ($CONF['UsingAdminArea'] && !$CONF['debug']) gets removed, + * application/xhtml+xml seems to be working, so we're going to use it if we can. + * + * @param string $content_type MIME media type registered to IANA, http://www.iana.org/assignments/media-types/index.html + * @param string $page_type + * @param string $charset Deprecated. This has no meaning. + * @return void + * + */ +function sendContentType($content_type, $page_type = '', $charset = '') +{ + global $manager, $CONF; + + if ( headers_sent() ) + { + return; + } + + /* NOTE: MIME Media Type */ + if ( ($content_type == 'application/xhtml+xml') + && (!stristr(serverVar('HTTP_ACCEPT'), 'application/xhtml+xml') ) ) + { + $content_type = 'text/html'; + } + + /* NOTE: generate event */ + $data = array( + 'pageType' => $page_type, + 'contentType' => &$content_type + ); + $manager->notify('PreSendContentType', $data); + + /* NOTE: confirm MIME Media Type */ + $content_type = preg_replace('#[^a-zA-Z0-9-+./]#', '', $content_type); + + /* NOTE: confirm character set */ + $charset = i18n::get_current_charset(); + if ( i18n::get_forced_charset() !== '' ) + { + $charset = i18n::get_forced_charset(); + } + + /* NOTE: send HTTP 1.1 header */ + header("Content-Type: {$content_type}; charset={$charset}"); + + /* NOTE: set handler for translating character set */ + if ( $charset != i18n::get_current_charset() ) + { + ob_start(array('i18n', 'convert_handler')); + } + + return; +} + +/** + * parseHighlight() + * This function parses a query into an array of expressions that can be passed on to the highlight method + * @param string $query + * @return void + */ +function parseHighlight($query) +{ + // TODO: add more intelligent splitting logic + + // get rid of quotes + $query = preg_replace('/\'|"/', '', $query); + + if ( !$query ) + { + return array(); + } + + $aHighlight = preg_split('# #', $query); + + for ( $i = 0; $i < count($aHighlight); $i++ ) + { + $aHighlight[$i] = trim($aHighlight[$i]); + + if ( i18n::strlen($aHighlight[$i]) < 3 ) + { + unset($aHighlight[$i]); + } + } + + if ( count($aHighlight) == 1 ) + { + return $aHighlight[0]; + } + else + { + return $aHighlight; + } + return; +} + +/** + * getConfig() + * + * @param void + * @return void + */ +function getConfig() +{ + global $CONF; + + $query = sprintf('SELECT * FROM %s', sql_table('config')); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $CONF[$row['name']] = $row['value']; + } + return; +} + +/** + * This function gets the blog ID from the blog name + * @param string $name + * @return + */ +function getBlogIDFromName($name) +{ + $query = sprintf('SELECT bnumber AS result FROM %s WHERE bshortname=%s', sql_table('blog'), DB::quoteValue($name)); + return DB::getValue($query); +} + +/** + * This function gets the blog name from the blog ID + * @param int $id + * @return object + */ +function getBlogNameFromID($id) +{ + $query = sprintf('SELECT bname AS result FROM %s WHERE bnumber=%d', sql_table('blog'), intval($id)); + return DB::getValue($query); +} + +/** + * This function gets the blog ID from the item ID + * @param int $item_id + * @return object + */ +function getBlogIDFromItemID($item_id) +{ + $query = sprintf('SELECT iblog AS result FROM %s WHERE inumber=%d', sql_table('item'), intval($item_id)); + return DB::getValue($query); +} + +/** + * This function gets the blog ID from the comment ID + * @param int $comment_id + * @return object + */ +function getBlogIDFromCommentID($comment_id) +{ + $query = sprintf('SELECT cblog AS result FROM %s WHERE cnumber=%d', sql_table('comment'), intval($comment_id)); + return DB::getValue($query); +} + +/** + * This function gets the blog ID from the category ID + * @param int $category_id + * @return object + */ +function getBlogIDFromCatID($category_id) +{ + $query = sprintf('SELECT cblog AS result FROM %s WHERE catid=%d', sql_table('category'), intval($category_id)); + return DB::getValue($query); +} + +/** + * This function gets the category ID from the category name + * @param int $name + * @return object + */ +function getCatIDFromName($name) +{ + $query = sprintf('SELECT catid AS result FROM %s WHERE cname=%s', sql_table('category'), DB::quoteValue($name)); + return DB::getValue($query); +} + + +/** + * functions to be used in index.php to select something + */ +function selectBlog($shortname) +{ + global $blogid, $archivelist; + $blogid = getBlogIDFromName($shortname); + + // also force archivelist variable, if it is set + if ( $archivelist ) + { + $archivelist = $blogid; + } + return; +} +function selectSkin($skinname) +{ + global $skinid; + $skinid = SKIN::getIdFromName($skinname); + return; +} +function selectCategory($cat) +{ + global $catid; + if ( is_numeric($cat) ) + { + $catid = (integer) $cat; + } + else + { + $catid = getCatIDFromName($cat); + } + return; +} +function selectItem($id) +{ + global $itemid; + $itemid = (integer) $id; + return; +} +function selectSpecialSkinType($id) +{ + global $special; + $special = strtolower($id); + return; +} +function selector() +{ + global $archive, $archivelist, $archivenext, $archivenextexists, $archiveprev, $archiveprevexists, $archivetype; + global $blog, $blogid; + global $catid; + global $itemid, $itemidnext, $itemidprev, $itemtitlenext, $itemtitleprev; + global $CONF, $DIR_LIBS, $amount, $errormessage, $imagepopup; + global $manager, $maxresults, $query; + global $member, $memberid, $memberinfo; + global $skinid, $skinpart, $special; + + $actionNames = array('addcomment', 'sendmessage', 'createaccount', 'forgotpassword', 'votepositive', 'votenegative', 'plugin'); + $action = requestVar('action'); + + if ( in_array($action, $actionNames) ) + { + include_once($DIR_LIBS . 'ACTION.php'); + $a = new Action(); + $errorInfo = $a->doAction($action); + + if ( $errorInfo ) + { + $errormessage = $errorInfo['message']; + } + } + + // show error when headers already sent out + if ( headers_sent() && $CONF['alertOnHeadersSent'] ) + { + // try to get line number/filename (extra headers_sent params only exists in PHP 4.3+) + if ( function_exists('version_compare') && version_compare('4.3.0', phpversion(), '<=') ) + { + headers_sent($hsFile, $hsLine); + $extraInfo = ' in ' . $hsFile . ' line ' . $hsLine . ''; + } + else + { + $extraInfo = ''; + } + + startUpError( + "

The page headers have already been sent out{$extraInfo}. This could cause Nucleus not to work in the expected way.

" + . "

Usually, this is caused by spaces or newlines at the end of the config.php file, " + . "at the end of the translation file or at the end of a plugin file.

" + . "

Please check this and try again.

" + . "

If you don't want to see this error message again, without solving the problem, " + . "set {$CONF['alertOnHeadersSent']} in globalfunctions.php to 0

" + . "Page headers already sent" + ); + exit; + } + + // make is so ?archivelist without blogname or blogid shows the archivelist + // for the default weblog + if ( serverVar('QUERY_STRING') == 'archivelist' ) + { + $archivelist = $CONF['DefaultBlog']; + } + + // now decide which type of skin we need + if ( $itemid ) + { + // itemid given -> only show that item + $type = 'item'; + + if ( !$manager->existsItem($itemid,intval($CONF['allowFuture']),intval($CONF['allowDrafts'])) ) + { + doError(_ERROR_NOSUCHITEM); + } + + // 1. get timestamp, blogid and catid for item + $query = 'SELECT itime, iblog, icat FROM %s WHERE inumber=%d'; + $query = sprintf($query, sql_table('item'), intval($itemid)); + $row = DB::getRow($query); + + // if a different blog id has been set through the request or selectBlog(), + // deny access + + if ( $blogid && (intval($blogid) != $row['iblog']) ) + { + doError(_ERROR_NOSUCHITEM); + } + + // if a category has been selected which doesn't match the item, ignore the + // category. #85 + if ( ($catid != 0) && ($catid != $row['icat']) ) + { + $catid = 0; + } + + $blogid = $row['iblog']; + $timestamp = strtotime($row['itime']); + + $b =& $manager->getBlog($blogid); + + if ( !$b->isValidCategory($catid) ) + { + $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d ORDER BY itime DESC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid)); + } + else + { + $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d AND icat=%d ORDER BY itime DESC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid), intval($catid)); + } + $row = DB::getRow($query); + + if ( $row ) + { + $itemidprev = $row['inumber']; + $itemtitleprev = $row['ititle']; + } + + // get next itemid and title + if ( !$b->isValidCategory($catid) ) + { + $query = "SELECT inumber, ititle FROM %s WHERE itime>%s AND itime<=%s AND idraft=0 AND iblog=%d ORDER BY itime ASC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid)); + } + else + { + $query = "SELECT inumber, ititle FROM %s WHERE itime>%s AND itime<=%s AND idraft=0 AND iblog=%d AND icat=%d ORDER BY itime ASC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid), intval($catid)); + } + $row = DB::getRow($query); + + if ( $row ) + { + $itemidnext = $row['inumber']; + $itemtitlenext = $row['ititle']; + } + } + elseif ( $archive ) + { + // show archive + $type = 'archive'; + + // sql queries for the timestamp of the first and the last published item + $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime ASC', sql_table('item')); + $first_timestamp = DB::getValue($query); + $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime DESC', sql_table('item')); + $last_timestamp = DB::getValue($query); + + sscanf($archive, '%d-%d-%d', $y, $m, $d); + + if ( $d != 0 ) + { + $archivetype = _ARCHIVETYPE_DAY; + $t = mktime(0, 0, 0, $m, $d, $y); + // one day has 24 * 60 * 60 = 86400 seconds + $archiveprev = i18n::formatted_datetime('%Y-%m-%d', $t - 86400 ); + // check for published items + if ( $t > $first_timestamp ) + { + $archiveprevexists = true; + } + else + { + $archiveprevexists = false; + } + + // one day later + $t += 86400; + $archivenext = i18n::formatted_datetime('%Y-%m-%d', $t); + if ( $t < $last_timestamp ) + { + $archivenextexists = true; + } + else + { + $archivenextexists = false; + } + } + elseif ( $m == 0 ) + { + $archivetype = _ARCHIVETYPE_YEAR; + $t = mktime(0, 0, 0, 12, 31, $y - 1); + // one day before is in the previous year + $archiveprev = i18n::formatted_datetime('%Y', $t); + if ( $t > $first_timestamp ) + { + $archiveprevexists = true; + } + else + { + $archiveprevexists = false; + } + + // timestamp for the next year + $t = mktime(0, 0, 0, 1, 1, $y + 1); + $archivenext = i18n::formatted_datetime('%Y', $t); + if ( $t < $last_timestamp ) + { + $archivenextexists = true; + } + else + { + $archivenextexists = false; + } + } + else + { + $archivetype = _ARCHIVETYPE_MONTH; + $t = mktime(0, 0, 0, $m, 1, $y); + // one day before is in the previous month + $archiveprev = i18n::formatted_datetime('%Y-%m', $t - 86400); + if ( $t > $first_timestamp ) + { + $archiveprevexists = true; + } + else + { + $archiveprevexists = false; + } + + // timestamp for the next month + $t = mktime(0, 0, 0, $m+1, 1, $y); + $archivenext = i18n::formatted_datetime('%Y-%m', $t); + if ( $t < $last_timestamp ) + { + $archivenextexists = true; + } + else + { + $archivenextexists = false; + } + } + } + elseif ( $archivelist ) + { + $type = 'archivelist'; + + if ( is_numeric($archivelist) ) + { + $blogid = intVal($archivelist); + } + else + { + $blogid = getBlogIDFromName($archivelist); + } + + if ( !$blogid ) + { + doError(_ERROR_NOSUCHBLOG); + } + } + elseif ( $query ) + { + global $startpos; + $type = 'search'; + $query = stripslashes($query); + + if ( is_numeric($blogid) ) + { + $blogid = intVal($blogid); + } + else + { + $blogid = getBlogIDFromName($blogid); + } + + if ( !$blogid ) + { + doError(_ERROR_NOSUCHBLOG); + } + } + elseif ( $memberid ) + { + $type = 'member'; + + if ( !Member::existsID($memberid) ) + { + doError(_ERROR_NOSUCHMEMBER); + } + $memberinfo = $manager->getMember($memberid); + } + elseif ( $imagepopup ) + { + // media object (images etc.) + $type = 'imagepopup'; + + // TODO: check if media-object exists + // TODO: set some vars? + } + else + { + // show regular index page + global $startpos; + $type = 'index'; + } + + // any type of skin with catid + if ( $catid && !$blogid ) + { + $blogid = getBlogIDFromCatID($catid); + } + + // decide which blog should be displayed + if ( !$blogid ) + { + $blogid = $CONF['DefaultBlog']; + } + + $b =& $manager->getBlog($blogid); + $blog = $b; // references can't be placed in global variables? + + if ( !$blog->isValid ) + { + doError(_ERROR_NOSUCHBLOG); + } + + // set catid if necessary + if ( $catid ) + { + // check if the category is valid + if ( !$blog->isValidCategory($catid) ) + { + doError(_ERROR_NOSUCHCATEGORY); + } + else + { + $blog->setSelectedCategory($catid); + } + } + + if ( !$skinid ) + { + $skinid = $blog->getDefaultSkin(); + } + + if ( !empty($special) && isValidShortName($special) ) + { + $type = strtolower($special); + } + + $skin = new SKIN($skinid); + + if ( !$skin->isValid() ) + { + doError(_ERROR_NOSUCHSKIN); + } + + // set global skinpart variable so can determine quickly what is being parsed from any plugin or phpinclude + $skinpart = $type; + + // parse the skin + $skin->parse($type); + + // check to see we should throw JustPosted event + $blog->checkJustPosted(); + return; +} + +/** + * doError() + * Show error skin with given message. An optional skin-object to use can be given + * + * @param string $msg + * @param string $skin + * @return void + */ +function doError($msg, $skin = '') +{ + global $errormessage, $CONF, $skinid, $blogid, $manager; + + if ( $skin == '' ) + { + if ( Skin::existsID($skinid) ) + { + $id = $skinid; + } + elseif ( $manager->existsBlogID($blogid) ) + { + $blog =& $manager->getBlog($blogid); + $id = $blog->getDefaultSkin(); + } + elseif ($CONF['DefaultBlog'] ) + { + $blog =& $manager->getBlog($CONF['DefaultBlog']); + $id = $blog->getDefaultSkin(); + } + else + { + // this statement should actually never be executed + $id = $CONF['BaseSkin']; + } + $skin = new Skin($id); + } + + $errormessage = $msg; + $skin->parse('error'); + return; +} + +/** + * Errors before the database connection has been made + * + * @param string $msg message to notify + * @param string $title page title + * @return void + */ +function startUpError($msg, $title) +{ + header('Content-Type: text/xml; charset=' . i18n::get_current_charset()); + echo "\n"; + echo "\n"; + echo "{$title}\n"; + echo "\n"; + echo "

{$title}

\n"; + echo $msg; + echo "\n"; + echo "\n"; + exit; +} + +function isValidShortName($name) +{ + return preg_match('#^[a-z0-9]+$#i', $name); +} +function isValidDisplayName($name) +{ + return preg_match('#^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$#i', $name); +} +function isValidCategoryName($name) +{ + return 1; +} +function isValidTemplateName($name) +{ + return preg_match('#^[a-z0-9/_\-]+$#i', $name); +} +function isValidSkinName($name) +{ + return preg_match('#^[a-z0-9/_\-]+$#i', $name); +} + +// add and remove linebreaks +function addBreaks($var) +{ + return nl2br($var); +} +function removeBreaks($var) +{ + return preg_replace("/
([\r\n])/", "$1", $var); +} + +/** + * parseFile() + * + * @param string $filename + * @param string $includeMode + * @param string $includePrefix + * @return void + */ +function parseFile($filename, $includeMode = 'normal', $includePrefix = '') +{ + global $skinid; + + if ( !$skinid || !existsID($skinid) ) + { + $skin = new Skin($CONF['BaseSkin']); + } + else + { + $skin = new Skin($skinid); + } + + $oldIncludeMode = Parser::getProperty('IncludeMode'); + $oldIncludePrefix = Parser::getProperty('IncludePrefix'); + + $skin->parse('fileparse', $filename); + + Parser::setProperty('IncludeMode', $oldIncludeMode); + Parser::setProperty('IncludePrefix', $oldIncludePrefix); + + return; +} + +/** + * debug() + * Outputs a debug message + * + * @param string $msg + * @return void + */ +function debug($msg) +{ + echo '

' . $msg . "

\n"; + return; +} + +// shows a link to help file +function help($id) +{ + echo helpHtml($id); + return; +} +function helpHtml($id) +{ + global $CONF; + return helplink($id) . '' . _HELP_TT . ''; +} +function helplink($id) +{ + global $CONF; + return ''; +} + +/** + * includephp() + * Includes a PHP file. This method can be called while parsing templates and skins + * + * @param string $filename name of file to parse + * @return void + */ +function includephp($filename) +{ + // make predefined variables global, so most simple scripts can be used here + + // apache (names taken from PHP doc) + global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL; + global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT; + global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE; + global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT; + global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN; + global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME; + global $REQUEST_URI; + + // php (taken from PHP doc) + global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS; + global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS; + + // other + global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR; + + if ( @file_exists($filename) ) + { + include($filename); + } + return; +} + +/** + * Checks if a certain plugin exists + * @param string $plug name of plugin + * @return boolean exists or not + */ +function checkPlugin($name) +{ + global $DIR_PLUGINS; + return file_exists($DIR_PLUGINS . preg_replace('#[\\\\|/]#', '', $name) . '.php'); +} + +/** + * alterQueryStr() + * + * @param string $querystr querystring to alter (e.g. foo=1&bar=2&x=y) + * @param string $param name of parameter to change (e.g. 'foo') + * @param string $value New value for that parameter (e.g. 3) + * @return string altered query string (for the examples above: foo=3&bar=2&x=y) + */ +function alterQueryStr($querystr, $param, $value) +{ + $vars = preg_split('#&#', $querystr); + $set = FALSE; + + for ( $i = 0; $i < count($vars); $i++ ) + { + $v = preg_split('#=#', $vars[$i]); + + if ( $v[0] == $param ) + { + $v[1] = $value; + $vars[$i] = implode('=', $v); + $set = true; + break; + } + } + if ( !$set ) + { + $vars[] = "{$param}={$value}"; + } + return ltrim(implode('&', $vars), '&'); +} + +/** + * passVar() + * passes one variable as hidden input field (multiple fields for arrays) + * @see passRequestVars in varsx.x.x.php + * + * @param string $key + * @param string $value + * @return void + */ +function passVar($key, $value) +{ + // array ? + if ( is_array($value) ) + { + for ( $i = 0; $i < sizeof($value); $i++ ) + { + passVar($key . '[' . $i . ']', $value[$i]); + } + return; + } + + // other values: do stripslashes if needed + echo '' . "\n"; + return; +} + +/** + * checkVars() + * + * @param string $variables + * @return void + */ +function checkVars($variables) +{ + foreach ( $variables as $variable ) + { + if ( array_key_exists($variable, $_GET) + || array_key_exists($variable, $_POST) + || array_key_exists($variable, $_COOKIE) + || array_key_exists($variable, $_ENV) + || (session_id() !== '' && array_key_exists($variable, $_SESSION)) + || array_key_exists($variable, $_FILES) ) + { + die('Sorry. An error occurred.'); + } + } + return; +} + +/** + * sanitizeParams() + * Sanitize parameters such as $_GET and $_SERVER['REQUEST_URI'] etc. + * to avoid XSS. + * + * @param void + * @return void + */ +function sanitizeParams() +{ + $array = array(); + $str = ''; + $frontParam = ''; + + // REQUEST_URI of $_SERVER + $str =& $_SERVER["REQUEST_URI"]; + serverStringToArray($str, $array, $frontParam); + sanitizeArray($array); + arrayToServerString($array, $frontParam, $str); + + // QUERY_STRING of $_SERVER + $str =& $_SERVER["QUERY_STRING"]; + serverStringToArray($str, $array, $frontParam); + sanitizeArray($array); + arrayToServerString($array, $frontParam, $str); + + // $_GET + convArrayForSanitizing($_GET, $array); + sanitizeArray($array); + revertArrayForSanitizing($array, $_GET); + + // $_REQUEST (only GET param) + convArrayForSanitizing($_REQUEST, $array); + sanitizeArray($array); + revertArrayForSanitizing($array, $_REQUEST); + + return; +} + +function _addInputTags(&$keys,$prefix='') +{ + foreach ( $keys as $key=>$value ) + { + if ( $prefix ) + { + $key=$prefix.'['.$key.']'; + } + if ( is_array($value) ) + { + _addInputTags($value,$key); + } + else + { + if ( get_magic_quotes_gpc() ) + {$value=stripslashes($value); + } + if ( $key == 'ticket' ) + { + continue; + } + echo ''."\n"; + } + } + return; +} + +/** + * serverStringToArray() + * Convert the server string such as $_SERVER['REQUEST_URI'] + * to arry like arry['blogid']=1 and array['page']=2 etc. + * + * @param string $uri string + * @param string &$query_elements elements of query according to application/x-www-form-urlencoded + * @param string &$hier_part hierarchical part includes path + * + * NOTE: + * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax + * 3. Syntax Components + * http://www.ietf.org/rfc/rfc3986.txt + * + * Hypertext Markup Language - 2.0 + * 8.2.1. The form-urlencoded Media Type + * http://tools.ietf.org/html/rfc1866#section-8.2.1 + * + * $_SERVER > Language Reference > Predefined Variables > PHP Manual + * http://www.php.net/manual/en/reserved.variables.server.php + */ +function serverStringToArray($uri, &$query_elements, &$hier_part) +{ + // init param + $query_elements = array(); + $hier_part = ""; + + // split hierarchical part, e.g. /index.php, query and fragment, e.g. blogid=1&page=2#section1 + if ( i18n::strpos($uri, "?") > 0 ) + { + list($hier_part, $query_and_fragment) = preg_split("#\?#", $uri, 2); + } + else + { + $query_and_fragment = $uri; + $hier_part = ''; + } + + // If there is no query like blogid=1&page=2, return + if ( i18n::strpos($uri, "=") == FALSE && !i18n::strlen($hier_part) ) + { + $hier_part = $uri; + return; + } + + $query_elements = preg_split("#&#", $query_and_fragment); + return; +} + +/** + * arrayToServerString() + * Convert array like array['blogid'] to server string + * such as $_SERVER['REQUEST_URI'] + * + * @param array $query_elements elements of query according to application/x-www-form-urlencoded + * @param string $hier_part hier-part defined in RFC3986 + * @param string &$uri return value + * @return void + * + * NOTE: + * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax + * 3. Syntax Components + * http://www.ietf.org/rfc/rfc3986.txt + * + * Hypertext Markup Language - 2.0 + * 8.2.1. The form-urlencoded Media Type + * http://tools.ietf.org/html/rfc1866#section-8.2.1 + * + * $_SERVER > Language Reference > Predefined Variables > PHP Manual + * http://www.php.net/manual/en/reserved.variables.server.php + */ +function arrayToServerString($query_elements, $hier_part, &$uri) +{ + if ( i18n::strpos($uri, "?") !== FALSE ) + { + $uri = $hier_part . "?"; + } + else + { + $uri = $hier_part; + } + if ( count($query_elements) > 0 ) + { + $uri .= implode("&", $query_elements); + } + return; +} + +/** + * sanitizeArray() + * Sanitize array parameters. + * This function checks both key and value. + * - check key if it inclues " (double quote), remove from array + * - check value if it includes \ (escape sequece), remove remaining string + * + * @param array &$array elements of query according to application/x-www-form-urlencoded + * @return void + */ +function sanitizeArray(&$array) +{ + $excludeListForSanitization = array('query'); + + foreach ( $array as $k => $v ) + { + // split to key and value + list($key, $val) = preg_split("#=#", $v, 2); + if ( !isset($val) ) + { + continue; + } + + // when magic quotes is on, need to use stripslashes, + // and then addslashes + if ( get_magic_quotes_gpc() ) + { + $val = stripslashes($val); + } + + // note that we must use addslashes here because this function is called before the db connection is made + // and sql_real_escape_string needs a db connection + $val = addslashes($val); + + // if $key is included in exclude list, skip this param + if ( !in_array($key, $excludeListForSanitization) ) + { + // check value + if ( i18n::strpos($val, '\\') > 0 ) + { + list($val, $tmp) = preg_split('#\\\\#', $val); + } + + // remove control code etc. + $val = strtr($val, "\0\r\n<>'\"", " "); + + // check key + if ( preg_match('#\"#', $key) > 0 ) + { + unset($array[$k]); + continue; + } + + // set sanitized info + $array[$k] = sprintf("%s=%s", $key, $val); + } + } + return; +} + +/** + * convArrayForSanitizing() + * Convert array for sanitizeArray function + * + * @param string $src array to be sanitized + * @param array &$array array to be temporarily stored + * @return void + */ +function convArrayForSanitizing($src, &$array) +{ + $array = array(); + foreach ( $src as $key => $val ) + { + if ( !key_exists($key, $_GET) ) + { + continue; + } + $array[] = sprintf("%s=%s", $key, $val); + continue; + } + return; +} + +/** + * revertArrayForSanitizing() + * Revert array after sanitizeArray function + * + * @param array $array element of query according to application/x-www-form-urlencoded + * @param array &$dst combination of key and value + * @return void + */ +function revertArrayForSanitizing($array, &$dst) +{ + foreach ( $array as $v ) + { + list($key, $val) = preg_split("#=#", $v, 2); + $dst[$key] = $val; + continue; + } + return; +} + +/** ++======= + 0 ) + { + $nucleus['version'] .= '/' . getNucleusPatchLevel(); + } + + /* Avoid notices */ + if ( !array_key_exists('installscript', $CONF) || empty($CONF['installscript']) ) + { + $CONF['installscript'] = 0; + } + if ( !array_key_exists('UsingAdminArea', $CONF) ) + { + $CONF['UsingAdminArea'] = 0; + } + + if ( !headers_sent() ) + { + header('Generator: Nucleus CMS ' . $nucleus['version']); + } + + + /* TODO: This is for compatibility since 4.0, should be obsoleted at future release. */ + if ( !isset($DIR_LOCALES) ) + { + $DIR_LOCALES = $DIR_NUCLEUS . 'locales/'; + } + global $DIR_LANG; + if ( !isset($DIR_LANG) ) + { + $DIR_LANG = $DIR_LOCALES; + } + + /* load and initialize i18n class */ + if (!class_exists('i18n', FALSE)) + { + include($DIR_LIBS . 'i18n.php'); + } + if ( !i18n::init('UTF-8', $DIR_LOCALES) ) + { + exit('Fail to initialize i18n class.'); + } + + /* TODO: This is just for compatibility since 4.0, should be obsoleted at future release. */ + define('_CHARSET', i18n::get_current_charset()); + + + /* + * NOTE: Since 4.0 release, Entity class becomes to be important class + * with some wrapper functions for htmlspechalchars/htmlentity PHP's built-in function + */ + include($DIR_LIBS . 'ENTITY.php'); + + /* we will use postVar, getVar, ... methods instead of $_GET, $_POST ... */ + if ( $CONF['installscript'] != 1 ) + { + /* vars were already included in install.php */ + include_once($DIR_LIBS . 'vars4.1.0.php'); + + /* added for 4.0 DB::* wrapper and compatibility sql_* */ + include_once($DIR_LIBS . 'sql/sql.php'); + } + + /* include core classes that are needed for login & plugin handling */ + include($DIR_LIBS . 'MEMBER.php'); + include($DIR_LIBS . 'ACTIONLOG.php'); + include($DIR_LIBS . 'MANAGER.php'); + include($DIR_LIBS . 'PLUGIN.php'); + + $manager =& MANAGER::instance(); + + /* only needed when updating logs */ + if ( $CONF['UsingAdminArea'] ) + { + /* XML-RPC client classes */ + include($DIR_LIBS . 'xmlrpc.inc.php'); + include($DIR_LIBS . 'ADMIN.php'); + } + + + /* connect to database */ + if ( !isset($MYSQL_HANDLER) ) + { + $MYSQL_HANDLER = array('mysql',''); + } + if ( $MYSQL_HANDLER[0] == '' ) + { + $MYSQL_HANDLER[0] = 'mysql'; + } + DB::setConnectionInfo($MYSQL_HANDLER[1], $MYSQL_HOST, $MYSQL_USER, $MYSQL_PASSWORD, $MYSQL_DATABASE); + + + /* force locale or charset */ + $locale = ''; + $charset = i18n::get_current_charset(); + + $data = array( + 'locale' => &$locale, + 'charset' => &$charset + ); + $manager->notify('ForceLocale', $data); + + if ( $data['locale'] !== '' ) + { + i18n::set_forced_locale($data['locale']); + } + if ( $data['charset'] !== '' ) + { + i18n::set_forced_charset($data['charset']); + } + unset($locale); + unset($charset); + + + /* convert forced charset to current charset */ + if ( i18n::get_forced_charset() != i18n::get_current_charset() ) + { + $_POST = i18n::convert_array($_POST, i18n::get_forced_charset()); + $_GET = i18n::convert_array($_GET, i18n::get_forced_charset()); + $_REQUEST = i18n::convert_array($_REQUEST, i18n::get_forced_charset()); + $_COOKIE = i18n::convert_array($_COOKIE, i18n::get_forced_charset()); + $_FILES = i18n::convert_array($_FILES, i18n::get_forced_charset()); + + if ( session_id() !== '' ) + { + $_SESSION = i18n::convert_array($_SESSION, i18n::get_forced_charset()); + } + } + + + /* sanitize option */ + $bLoggingSanitizedResult = 0; + $bSanitizeAndContinue = 0; + $orgRequestURI = serverVar('REQUEST_URI'); + sanitizeParams(); + + /* logs sanitized result if need */ + if ( $orgRequestURI !== serverVar('REQUEST_URI') ) + { + $msg = "Sanitized [" . serverVar('REMOTE_ADDR') . "] "; + $msg .= $orgRequestURI . " -> " . serverVar('REQUEST_URI'); + if ( $bLoggingSanitizedResult ) + { + addToLog(WARNING, $msg); + } + if ( !$bSanitizeAndContinue ) + { + die(""); + } + } + + /* get all variables that can come from the request and put them in the global scope */ + $blogid = requestVar('blogid'); + $itemid = intRequestVar('itemid'); + $catid = intRequestVar('catid'); + $skinid = requestVar('skinid'); + $memberid = requestVar('memberid'); + $archivelist = requestVar('archivelist'); + $imagepopup = requestVar('imagepopup'); + $archive = requestVar('archive'); + $query = requestVar('query'); + $highlight = requestVar('highlight'); + $amount = requestVar('amount'); + $action = requestVar('action'); + $nextaction = requestVar('nextaction'); + $maxresults = requestVar('maxresults'); + $startpos = intRequestVar('startpos'); + $errormessage = ''; + $error = ''; + $special = requestVar('special'); + + + /* read config */ + getConfig(); + + + /* Properly set $CONF['Self'] and others if it's not set... + * usually when we are access from admin menu + */ + if ( !array_key_exists('Self', $CONF) ) + { + $CONF['Self'] = $CONF['IndexURL']; + /* strip trailing */ + if ( $CONF['Self'][i18n::strlen($CONF['Self']) -1] == "/" ) + { + $CONF['Self'] = i18n::substr($CONF['Self'], 0, i18n::strlen($CONF['Self']) -1); + } + } + + $CONF['ItemURL'] = $CONF['Self']; + $CONF['ArchiveURL'] = $CONF['Self']; + $CONF['ArchiveListURL'] = $CONF['Self']; + $CONF['MemberURL'] = $CONF['Self']; + $CONF['SearchURL'] = $CONF['Self']; + $CONF['BlogURL'] = $CONF['Self']; + $CONF['CategoryURL'] = $CONF['Self']; + + /* automatically use simpler toolbar for mozilla */ + if ( ($CONF['DisableJsTools'] == 0) + && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Mozilla/5.0') !== FALSE + && i18n::strpos(serverVar('HTTP_USER_AGENT'), 'Gecko') !== FALSE ) + { + $CONF['DisableJsTools'] = 2; + } + + /* login processing */ + $member = new Member(); + if ( $action == 'login' ) + { + $login = postVar('login'); + $password = postVar('password'); + $shared = intPostVar('shared'); + $member->login($login, $password, $shared); + } + elseif ( ($action == 'logout') ) + { + $member->logout(); + } + else + { + $member->cookielogin(); + } + + /* TODO: This is for backward compatibility, should be obsoleted near future. */ + if ( !preg_match('#^(.+)_(.+)_(.+)$#', $CONF['Locale']) + && ($CONF['Locale'] = i18n::convert_old_language_file_name_to_locale($CONF['Locale'])) === FALSE ) + { + $CONF['Locale'] = 'en_Latn_US'; + } + if ( !array_key_exists('Language', $CONF) ) + { + $CONF['Language'] = i18n::convert_locale_to_old_language_file_name($CONF['Locale']); + } + $locale = $CONF['Locale']; + + + /* NOTE: include translation file and set locale */ + if ( $member->isLoggedIn() ) + { + if ( $member->getLocale() ) + { + $locale = $member->getLocale(); + } + } + else + { + if ( i18n::get_forced_locale() !== '' ) + { + $locale = i18n::get_forced_locale(); + } + } + include_translation($locale); + i18n::set_current_locale($locale); + + + /* login completed */ + $data = array('loggedIn' => $member->isLoggedIn()); + $manager->notify('PostAuthentication', $data); + + /* next action */ + if ( $member->isLoggedIn() && $nextaction ) + { + $action = $nextaction; + } + + /* first, let's see if the site is disabled or not. always allow admin area access. */ + if ( $CONF['DisableSite'] && !$member->isAdmin() && !$CONF['UsingAdminArea'] ) + { + redirect($CONF['DisableSiteURL']); + exit; + } + + /* load other classes */ + include($DIR_LIBS . 'PARSER.php'); + include($DIR_LIBS . 'SKIN.php'); + include($DIR_LIBS . 'TEMPLATE.php'); + include($DIR_LIBS . 'BLOG.php'); + include($DIR_LIBS . 'BODYACTIONS.php'); + include($DIR_LIBS . 'COMMENTS.php'); + include($DIR_LIBS . 'COMMENT.php'); + include($DIR_LIBS . 'NOTIFICATION.php'); + include($DIR_LIBS . 'BAN.php'); + include($DIR_LIBS . 'SEARCH.php'); + include($DIR_LIBS . 'LINK.php'); + + /* set lastVisit cookie (if allowed) */ + if ( !headers_sent() ) + { + if ( $CONF['LastVisit'] ) + { + setcookie($CONF['CookiePrefix'] . 'lastVisit', time(), time() + 2592000, $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + } + else + { + setcookie($CONF['CookiePrefix'] . 'lastVisit', '', (time() - 2592000), $CONF['CookiePath'], $CONF['CookieDomain'], $CONF['CookieSecure']); + } + } + + /* for path resolving */ + $virtualpath = getVar('virtualpath'); + if ( getVar('virtualpath') == '' ) + { + $virtualpath = serverVar('PATH_INFO'); + } + + /* + * switch URLMode back to normal when $CONF['Self'] ends in .php + * this avoids urls like index.php/item/13/index.php/item/15 + */ + if ( !array_key_exists('URLMode', $CONF) || ($CONF['URLMode'] != 'pathinfo') ) + { + $CONF['URLMode'] = 'normal'; + } + else + { + if ( i18n::substr($CONF['Self'], i18n::strlen($CONF['Self']) - 4) != '.php' ) + { + decodePathInfo($virtualpath); + } + } + + /* + * PostParseURL is a place to cleanup any of the path-related global variables before the selector function is run. + * It has 2 values in the data in case the original virtualpath is needed, but most the use will be in tweaking + * global variables to clean up (scrub out catid or add catid) or to set someother global variable based on + * the values of something like catid or itemid + * New in 3.60 + */ + $data = array( + 'type' => basename(serverVar('SCRIPT_NAME')), + 'info' => $virtualpath + ); + $manager->notify('PostParseURL', $data); + + /* + * NOTE: Here is the end of initialization + */ + + /** + * include_libs() + * This function includes or requires the specified library file + * + * @param string $file + * @param boolean $once use the _once() version + * @param boolean $require use require() instead of include() + * @return void + */ + function include_libs($file, $once = TRUE, $require = TRUE) + { + global $DIR_LIBS; + + // $DIR_LIBS isn't a directory + if ( !is_dir($DIR_LIBS) ) + { + exit; + } + + $lib_path = $DIR_LIBS . $file; + + if ( $once && $require ) + { + require_once($lib_path); + } + else if ( $once && !$require ) + { + include_once($lib_path); + } + else if ( $require ) + { + require($lib_path); + } + else + { + include($lib_path); + } + return; + } + + /** + * include_plugins() + * This function includes or requires the specified plugin file + * + * @param string $file + * @param boolean $once use the _once() version + * @param boolean $require use require() instead of include() + * @return + */ + function include_plugins($file, $once = TRUE, $require = TRUE) + { + global $DIR_PLUGINS; + + // begin if: $DIR_LIBS isn't a directory + if ( !is_dir($DIR_PLUGINS) ) + { + exit; + } + + $plugin_path = $DIR_PLUGINS . $file; + + // begin if: + if ( $once && $require ) + { + require_once($plugin_path); + } + else if ( $once && !$require ) + { + include_once($plugin_path); + } + elseif ( $require ) + { + require($plugin_path); + } + else + { + include($plugin_path); + } + return; + } + + /** + * include_translation() + * This function decide which locale is used and include translation + * + * @param string &$locale locale name referring to 'language tags' defined in RFC 5646 + * @return void + */ + function include_translation(&$locale) + { + global $DIR_LOCALES; + + $translation_file = $DIR_LOCALES . $locale . '.' . i18n::get_current_charset() . '.php'; + if ( !file_exists($translation_file) ) + { + $locale = 'en_Latn_US'; + $translation_file = $DIR_LOCALES . 'en_Latn_US.ISO-8859-1.php'; + } + include($translation_file); + + /* + * NOTE: + * PHP is written by C and utilize C library, whose APIs are defined in POSIX. + * + * setlocale() is one of APIs of C library. + * but the argument value for setlocale() depends on each implements + * + * The latest POSIX standard: + * The Open Group Base Specifications Issue 7 + * IEEE Std 1003.1™-2008 + * http://pubs.opengroup.org/onlinepubs/9699919799/mindex.html + * + * Microsoft's operating system uses their own implementation + * Language Strings + * http://msdn.microsoft.com/en-us/library/39cwe7zf%28v=vs.110%29.aspx + * Country/Region Strings + * http://msdn.microsoft.com/en-us/library/cdax410z%28v=vs.110%29.aspx + * + * Linux and Unix (in this meaning, Apple's OS X derives from UNIX) uses ISO standard. + * two characters language tag (ISO 639-1) + * two characters region and country lag (ISO 3166-1 alpha-1) + * + */ + if ( PHP_OS == "WIN32" || PHP_OS == "WINNT" ) + { + /* LOCALE_IN_WINDOWS is defined in each translation files */ + setlocale(LC_ALL, _LOCALE_IN_WINDOWS); + } + else + { + setlocale(LC_ALL, preg_replace('#(.+)_(.+)_(.+)#', '$1-$3', $locale)); + } + return; + } + + /** + * intPostVar() + * This function returns the integer value of $_POST for the variable $name + * + * @param string $name field to get the integer value of + * @return integer + */ + function intPostVar($name) + { + return (integer) postVar($name); + } + + + /** + * intGetVar() + * This function returns the integer value of $_GET for the variable $name + * + * @param string $name field to get the integer value of + * @return integer + */ + function intGetVar($name) + { + return (integer) getVar($name); + } + + + /** + * intRequestVar() + * This function returns the integer value of $_REQUEST for the variable $name. Also checks $_GET and $_POST if not found in $_REQUEST + * + * @param string $name field to get the integer value of + * @return int + */ + function intRequestVar($name) + { + return (integer) requestVar($name); + } + + + /** + * intCookieVar() + * This function returns the integer value of $_COOKIE for the variable $name + * + * @param string $name field to get the integer value of + * @return integer + */ + function intCookieVar($name) + { + return (integer) cookieVar($name); + } + + /** + * getNucleusVersion() + * This function returns the current Nucleus version (100 = 1.00, 101 = 1.01, etc...) + * + * @param void + * @return integer + */ + function getNucleusVersion() + { + return 400; + } + + /** + * getNucleusPatchLevel() + * TODO: Better description of this function. + * + * Power users can install patches in between nucleus releases. These patches + * usually add new functionality in the plugin API and allow those to + * be tested without having to install CVS. + * + *@param void + * @return integer + */ + function getNucleusPatchLevel() + { + return 0; + } + + /** + * getLatestVersion() + * This function returns the latest Nucleus version available for download from nucleuscms.org or FALSE if unable to attain data + * Format will be major.minor/patachlevel e.g. 3.41 or 3.41/02 + * + * @param void + * @return mixed + */ + function getLatestVersion() + { + // begin if: cURL is not available in this PHP installation + if ( !function_exists('curl_init') ) + { + return FALSE; + } + + $curl = curl_init(); + $timeout = 5; + + curl_setopt ($curl, CURLOPT_URL, 'http://nucleuscms.org/version_check.php'); + curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout); + + $return = curl_exec($curl); + + curl_close($curl); + + return $return; + } + + /** + * sql_table() + * This function returns a Nucleus table name with the appropriate prefix + * @param string $name + * @return string + */ + function sql_table($name) + { + global $MYSQL_PREFIX; + + // begin if: no MySQL prefix + if ( empty($MYSQL_PREFIX) ) + { + return 'nucleus_' . $name; + } + // else: use MySQL prefix + else + { + return $MYSQL_PREFIX . 'nucleus_' . $name; + } + return; + } + + /** + * sendContentType() + * This function sends the Content-Type header if headers have not already been sent + * It also determines if the browser can accept application/xhtml+xml and sends it only to those that can. + * + * if content type is application/xhtml+xml, only send it to browsers + * that can handle it (IE6 cannot). Otherwise, send text/html + * + * v2.5: + * For admin area pages, keep sending text/html (unless it's a debug version) + * application/xhtml+xml still causes too much problems with the javascript implementations + * + * v3.3: + * ($CONF['UsingAdminArea'] && !$CONF['debug']) gets removed, + * application/xhtml+xml seems to be working, so we're going to use it if we can. + * + * @param string $content_type MIME media type registered to IANA, http://www.iana.org/assignments/media-types/index.html + * @param string $page_type + * @param string $charset Deprecated. This has no meaning. + * @return void + * + */ + function sendContentType($content_type, $page_type = '', $charset = '') + { + global $manager, $CONF; + + if ( headers_sent() ) + { + return; + } + + /* NOTE: MIME Media Type */ + if ( ($content_type == 'application/xhtml+xml') + && (!stristr(serverVar('HTTP_ACCEPT'), 'application/xhtml+xml') ) ) + { + $content_type = 'text/html'; + } + + /* NOTE: generate event */ + $data = array( + 'pageType' => $page_type, + 'contentType' => &$content_type + ); + $manager->notify('PreSendContentType', $data); + + /* NOTE: confirm MIME Media Type */ + $content_type = preg_replace('#[^a-zA-Z0-9-+./]#', '', $content_type); + + /* NOTE: confirm character set */ + $charset = i18n::get_current_charset(); + if ( i18n::get_forced_charset() !== '' ) + { + $charset = i18n::get_forced_charset(); + } + + /* NOTE: send HTTP 1.1 header */ + header("Content-Type: {$content_type}; charset={$charset}"); + + /* NOTE: set handler for translating character set */ + if ( $charset != i18n::get_current_charset() ) + { + ob_start(array('i18n', 'convert_handler')); + } + + return; + } + + /** + * parseHighlight() + * This function parses a query into an array of expressions that can be passed on to the highlight method + * @param string $query + * @return void + */ + function parseHighlight($query) + { + // TODO: add more intelligent splitting logic + + // get rid of quotes + $query = preg_replace('/\'|"/', '', $query); + + if ( !$query ) + { + return array(); + } + + $aHighlight = preg_split('# #', $query); + + for ( $i = 0; $i < count($aHighlight); $i++ ) + { + $aHighlight[$i] = trim($aHighlight[$i]); + + if ( i18n::strlen($aHighlight[$i]) < 3 ) + { + unset($aHighlight[$i]); + } + } + + if ( count($aHighlight) == 1 ) + { + return $aHighlight[0]; + } + else + { + return $aHighlight; + } + return; + } + + /** + * getConfig() + * + * @param void + * @return void + */ + function getConfig() + { + global $CONF; + + $query = sprintf('SELECT * FROM %s', sql_table('config')); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $CONF[$row['name']] = $row['value']; + } + return; + } + + /** + * This function gets the blog ID from the blog name + * @param string $name + * @return + */ + function getBlogIDFromName($name) + { + $query = sprintf('SELECT bnumber AS result FROM %s WHERE bshortname=%s', sql_table('blog'), DB::quoteValue($name)); + return DB::getValue($query); + } + + /** + * This function gets the blog name from the blog ID + * @param int $id + * @return object + */ + function getBlogNameFromID($id) + { + $query = sprintf('SELECT bname AS result FROM %s WHERE bnumber=%d', sql_table('blog'), intval($id)); + return DB::getValue($query); + } + + /** + * This function gets the blog ID from the item ID + * @param int $item_id + * @return object + */ + function getBlogIDFromItemID($item_id) + { + $query = sprintf('SELECT iblog AS result FROM %s WHERE inumber=%d', sql_table('item'), intval($item_id)); + return DB::getValue($query); + } + + /** + * This function gets the blog ID from the comment ID + * @param int $comment_id + * @return object + */ + function getBlogIDFromCommentID($comment_id) + { + $query = sprintf('SELECT cblog AS result FROM %s WHERE cnumber=%d', sql_table('comment'), intval($comment_id)); + return DB::getValue($query); + } + + /** + * This function gets the blog ID from the category ID + * @param int $category_id + * @return object + */ + function getBlogIDFromCatID($category_id) + { + $query = sprintf('SELECT cblog AS result FROM %s WHERE catid=%d', sql_table('category'), intval($category_id)); + return DB::getValue($query); + } + + /** + * This function gets the category ID from the category name + * @param int $name + * @return object + */ + function getCatIDFromName($name) + { + $query = sprintf('SELECT catid AS result FROM %s WHERE cname=%s', sql_table('category'), DB::quoteValue($name)); + return DB::getValue($query); + } + + + /** + * functions to be used in index.php to select something + */ + function selectBlog($shortname) + { + global $blogid, $archivelist; + $blogid = getBlogIDFromName($shortname); + + // also force archivelist variable, if it is set + if ( $archivelist ) + { + $archivelist = $blogid; + } + return; + } + function selectSkin($skinname) + { + global $skinid; + $skinid = SKIN::getIdFromName($skinname); + return; + } + function selectCategory($cat) + { + global $catid; + if ( is_numeric($cat) ) + { + $catid = (integer) $cat; + } + else + { + $catid = getCatIDFromName($cat); + } + return; + } + function selectItem($id) + { + global $itemid; + $itemid = (integer) $id; + return; + } + function selectSpecialSkinType($id) + { + global $special; + $special = strtolower($id); + return; + } + function selector() + { + global $archive, $archivelist, $archivenext, $archivenextexists, $archiveprev, $archiveprevexists, $archivetype; + global $blog, $blogid; + global $catid; + global $itemid, $itemidnext, $itemidprev, $itemtitlenext, $itemtitleprev; + global $CONF, $DIR_LIBS, $amount, $errormessage, $imagepopup; + global $manager, $maxresults, $query; + global $member, $memberid, $memberinfo; + global $skinid, $skinpart, $special; + + $actionNames = array('addcomment', 'sendmessage', 'createaccount', 'forgotpassword', 'votepositive', 'votenegative', 'plugin'); + $action = requestVar('action'); + + if ( in_array($action, $actionNames) ) + { + include_once($DIR_LIBS . 'ACTION.php'); + $a = new Action(); + $errorInfo = $a->doAction($action); + + if ( $errorInfo ) + { + $errormessage = $errorInfo['message']; + } + } + + // show error when headers already sent out + if ( headers_sent() && $CONF['alertOnHeadersSent'] ) + { + // try to get line number/filename (extra headers_sent params only exists in PHP 4.3+) + if ( function_exists('version_compare') && version_compare('4.3.0', phpversion(), '<=') ) + { + headers_sent($hsFile, $hsLine); + $extraInfo = ' in ' . $hsFile . ' line ' . $hsLine . ''; + } + else + { + $extraInfo = ''; + } + + startUpError( + "

The page headers have already been sent out{$extraInfo}. This could cause Nucleus not to work in the expected way.

" + . "

Usually, this is caused by spaces or newlines at the end of the config.php file, " + . "at the end of the translation file or at the end of a plugin file.

" + . "

Please check this and try again.

" + . "

If you don't want to see this error message again, without solving the problem, " + . "set {$CONF['alertOnHeadersSent']} in globalfunctions.php to 0

" + . "Page headers already sent" + ); + exit; + } + + // make is so ?archivelist without blogname or blogid shows the archivelist + // for the default weblog + if ( serverVar('QUERY_STRING') == 'archivelist' ) + { + $archivelist = $CONF['DefaultBlog']; + } + + // now decide which type of skin we need + if ( $itemid ) + { + // itemid given -> only show that item + $type = 'item'; + + if ( !$manager->existsItem($itemid,intval($CONF['allowFuture']),intval($CONF['allowDrafts'])) ) + { + doError(_ERROR_NOSUCHITEM); + return; + } + + // 1. get timestamp, blogid and catid for item + $query = 'SELECT itime, iblog, icat FROM %s WHERE inumber=%d'; + $query = sprintf($query, sql_table('item'), intval($itemid)); + $row = DB::getRow($query); + + // if a different blog id has been set through the request or selectBlog(), + // deny access + + if ( $blogid && (intval($blogid) != $row['iblog']) ) + { + doError(_ERROR_NOSUCHITEM); + return; + } + + // if a category has been selected which doesn't match the item, ignore the + // category. #85 + if ( ($catid != 0) && ($catid != $row['icat']) ) + { + $catid = 0; + } + + $blogid = $row['iblog']; + $timestamp = strtotime($row['itime']); + + $b =& $manager->getBlog($blogid); + + if ( !$b->isValidCategory($catid) ) + { + $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d ORDER BY itime DESC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid)); + } + else + { + $query = "SELECT inumber, ititle FROM %s WHERE itime<%s AND idraft=0 AND iblog=%d AND icat=%d ORDER BY itime DESC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), intval($blogid), intval($catid)); + } + $row = DB::getRow($query); + + if ( $row ) + { + $itemidprev = $row['inumber']; + $itemtitleprev = $row['ititle']; + } + + // get next itemid and title + if ( !$b->isValidCategory($catid) ) + { + $query = "SELECT inumber, ititle FROM %s WHERE itime>%s AND itime<=%s AND idraft=0 AND iblog=%d ORDER BY itime ASC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid)); + } + else + { + $query = "SELECT inumber, ititle FROM %s WHERE itime>%s AND itime<=%s AND idraft=0 AND iblog=%d AND icat=%d ORDER BY itime ASC LIMIT 1"; + $query = sprintf($query, sql_table('item'), DB::formatDateTime($timestamp), DB::formatDateTime($b->getCorrectTime()), intval($blogid), intval($catid)); + } + $row = DB::getRow($query); + + if ( $row ) + { + $itemidnext = $row['inumber']; + $itemtitlenext = $row['ititle']; + } + } + elseif ( $archive ) + { + // show archive + $type = 'archive'; + + // sql queries for the timestamp of the first and the last published item + $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime ASC', sql_table('item')); + $first_timestamp = DB::getValue($query); + $query = sprintf('SELECT UNIX_TIMESTAMP(itime) as result FROM %s WHERE idraft=0 ORDER BY itime DESC', sql_table('item')); + $last_timestamp = DB::getValue($query); + + sscanf($archive, '%d-%d-%d', $y, $m, $d); + + if ( $d != 0 ) + { + $archivetype = _LABEL_DAY_UNIT; + $t = mktime(0, 0, 0, $m, $d, $y); + // one day has 24 * 60 * 60 = 86400 seconds + $archiveprev = i18n::formatted_datetime('%Y-%m-%d', $t - 86400 ); + // check for published items + if ( $t > $first_timestamp ) + { + $archiveprevexists = true; + } + else + { + $archiveprevexists = false; + } + + // one day later + $t += 86400; + $archivenext = i18n::formatted_datetime('%Y-%m-%d', $t); + if ( $t < $last_timestamp ) + { + $archivenextexists = true; + } + else + { + $archivenextexists = false; + } + } + elseif ( $m == 0 ) + { + $archivetype = _LABEL_YEAR_UNIT; + $t = mktime(0, 0, 0, 12, 31, $y - 1); + // one day before is in the previous year + $archiveprev = i18n::formatted_datetime('%Y', $t); + if ( $t > $first_timestamp ) + { + $archiveprevexists = true; + } + else + { + $archiveprevexists = false; + } + + // timestamp for the next year + $t = mktime(0, 0, 0, 1, 1, $y + 1); + $archivenext = i18n::formatted_datetime('%Y', $t); + if ( $t < $last_timestamp ) + { + $archivenextexists = true; + } + else + { + $archivenextexists = false; + } + } + else + { + $archivetype = _LABEL_MONTH_UNIT; + $t = mktime(0, 0, 0, $m, 1, $y); + // one day before is in the previous month + $archiveprev = i18n::formatted_datetime('%Y-%m', $t - 86400); + if ( $t > $first_timestamp ) + { + $archiveprevexists = true; + } + else + { + $archiveprevexists = false; + } + + // timestamp for the next month + $t = mktime(0, 0, 0, $m+1, 1, $y); + $archivenext = i18n::formatted_datetime('%Y-%m', $t); + if ( $t < $last_timestamp ) + { + $archivenextexists = true; + } + else + { + $archivenextexists = false; + } + } + } + elseif ( $archivelist ) + { + $type = 'archivelist'; + + if ( is_numeric($archivelist) ) + { + $blogid = intVal($archivelist); + } + else + { + $blogid = getBlogIDFromName($archivelist); + } + + if ( !$blogid ) + { + doError(_ERROR_NOSUCHBLOG); + return; + } + } + elseif ( $query ) + { + global $startpos; + $type = 'search'; + $query = stripslashes($query); + + if ( is_numeric($blogid) ) + { + $blogid = intVal($blogid); + } + else + { + $blogid = getBlogIDFromName($blogid); + } + + if ( !$blogid ) + { + doError(_ERROR_NOSUCHBLOG); + return; + } + } + elseif ( $memberid ) + { + $type = 'member'; + + if ( !Member::existsID($memberid) ) + { + doError(_ERROR_NOSUCHMEMBER); + return; + } + $memberinfo = $manager->getMember($memberid); + } + elseif ( $imagepopup ) + { + // media object (images etc.) + $type = 'imagepopup'; + + // TODO: check if media-object exists + // TODO: set some vars? + } + else + { + // show regular index page + global $startpos; + $type = 'index'; + } + + // any type of skin with catid + if ( $catid && !$blogid ) + { + $blogid = getBlogIDFromCatID($catid); + } + + // decide which blog should be displayed + if ( !$blogid ) + { + $blogid = $CONF['DefaultBlog']; + } + + $b =& $manager->getBlog($blogid); + $blog = $b; // references can't be placed in global variables? + + if ( !$blog->isValid ) + { + doError(_ERROR_NOSUCHBLOG); + return; + } + + // set catid if necessary + if ( $catid ) + { + // check if the category is valid + if ( !$blog->isValidCategory($catid) ) + { + doError(_ERROR_NOSUCHCATEGORY); + return; + } + else + { + $blog->setSelectedCategory($catid); + } + } + + if ( !$skinid ) + { + $skinid = $blog->getDefaultSkin(); + } + + if ( !empty($special) && isValidShortName($special) ) + { + $type = strtolower($special); + } + + $skin =& $manager->getSkin($skinid); + + if ( !$skin->isValid() ) + { + doError(_ERROR_NOSUCHSKIN); + return; + } + + // set global skinpart variable so can determine quickly what is being parsed from any plugin or phpinclude + $skinpart = $type; + + // parse the skin + $skin->parse($type); + + // check to see we should throw JustPosted event + $blog->checkJustPosted(); + return; + } + + /** + * doError() + * Show error skin with given message. An optional skin-object to use can be given + * + * @param string $msg + * @param string $skin + * @return void + */ + function doError($msg, $skin = '') + { + global $errormessage, $CONF, $skinid, $blogid, $manager; + + if ( $skin == '' ) + { + if ( Skin::existsID($skinid) ) + { + $id = $skinid; + } + elseif ( $manager->existsBlogID($blogid) ) + { + $blog =& $manager->getBlog($blogid); + $id = $blog->getDefaultSkin(); + } + elseif ($CONF['DefaultBlog'] ) + { + $blog =& $manager->getBlog($CONF['DefaultBlog']); + $id = $blog->getDefaultSkin(); + } + else + { + // this statement should actually never be executed + $id = $CONF['BaseSkin']; + } + $skin =& $manager->getSkin($id); + } + + $errormessage = $msg; + $skin->parse('error'); + return; + } + + /** + * Errors before the database connection has been made + * + * @param string $msg message to notify + * @param string $title page title + * @return void + */ + function startUpError($msg, $title) + { + header('Content-Type: text/xml; charset=' . i18n::get_current_charset()); + echo "\n"; + echo "\n"; + echo "{$title}\n"; + echo "\n"; + echo "

{$title}

\n"; + echo $msg; + echo "\n"; + echo "\n"; + exit; + } + + function isValidShortName($name) + { + return preg_match('#^[a-z0-9]+$#i', $name); + } + function isValidDisplayName($name) + { + return preg_match('#^[a-z0-9]+[a-z0-9 ]*[a-z0-9]+$#i', $name); + } + function isValidCategoryName($name) + { + return 1; + } + function isValidTemplateName($name) + { + return preg_match('#^[a-z0-9/_\-]+$#i', $name); + } + function isValidSkinName($name) + { + return preg_match('#^[a-z0-9/_\-]+$#i', $name); + } + + // add and remove linebreaks + function addBreaks($var) + { + return nl2br($var); + } + function removeBreaks($var) + { + return preg_replace("/
([\r\n])/", "$1", $var); + } + + /** + * parseFile() + * + * @param string $filename + * @param string $includeMode + * @param string $includePrefix + * @return void + */ + function parseFile($filename, $includeMode = 'normal', $includePrefix = '') + { + global $manager, $skinid; + + if ( !$skinid || !existsID($skinid) ) + { + $skin =& $manager->getSkin($CONF['BaseSkin']); + } + else + { + $skin =& $manager->getSkin($skinid); + } + + $oldIncludeMode = Parser::getProperty('IncludeMode'); + $oldIncludePrefix = Parser::getProperty('IncludePrefix'); + + $skin->parse('fileparse', $filename); + + Parser::setProperty('IncludeMode', $oldIncludeMode); + Parser::setProperty('IncludePrefix', $oldIncludePrefix); + + return; + } + + /** + * debug() + * Outputs a debug message + * + * @param string $msg + * @return void + */ + function debug($msg) + { + echo '

' . $msg . "

\n"; + return; + } + + // shows a link to help file + function help($id) + { + echo helpHtml($id); + return; + } + function helpHtml($id) + { + global $CONF; + return helplink($id) . '' . _HELP_TT . '
'; + } + function helplink($id) + { + global $CONF; + return ''; + } + + /** + * includephp() + * Includes a PHP file. This method can be called while parsing templates and skins + * + * @param string $filename name of file to parse + * @return void + */ + function includephp($filename) + { + // make predefined variables global, so most simple scripts can be used here + + // apache (names taken from PHP doc) + global $GATEWAY_INTERFACE, $SERVER_NAME, $SERVER_SOFTWARE, $SERVER_PROTOCOL; + global $REQUEST_METHOD, $QUERY_STRING, $DOCUMENT_ROOT, $HTTP_ACCEPT; + global $HTTP_ACCEPT_CHARSET, $HTTP_ACCEPT_ENCODING, $HTTP_ACCEPT_LANGUAGE; + global $HTTP_CONNECTION, $HTTP_HOST, $HTTP_REFERER, $HTTP_USER_AGENT; + global $REMOTE_ADDR, $REMOTE_PORT, $SCRIPT_FILENAME, $SERVER_ADMIN; + global $SERVER_PORT, $SERVER_SIGNATURE, $PATH_TRANSLATED, $SCRIPT_NAME; + global $REQUEST_URI; + + // php (taken from PHP doc) + global $argv, $argc, $PHP_SELF, $HTTP_COOKIE_VARS, $HTTP_GET_VARS, $HTTP_POST_VARS; + global $HTTP_POST_FILES, $HTTP_ENV_VARS, $HTTP_SERVER_VARS, $HTTP_SESSION_VARS; + + // other + global $PATH_INFO, $HTTPS, $HTTP_RAW_POST_DATA, $HTTP_X_FORWARDED_FOR; + + if ( @file_exists($filename) ) + { + include($filename); + } + return; + } + + /** + * Checks if a certain plugin exists + * @param string $plug name of plugin + * @return boolean exists or not + */ + function checkPlugin($name) + { + global $DIR_PLUGINS; + return file_exists($DIR_PLUGINS . preg_replace('#[\\\\|/]#', '', $name) . '.php'); + } + + /** + * alterQueryStr() + * + * @param string $querystr querystring to alter (e.g. foo=1&bar=2&x=y) + * @param string $param name of parameter to change (e.g. 'foo') + * @param string $value New value for that parameter (e.g. 3) + * @return string altered query string (for the examples above: foo=3&bar=2&x=y) + */ + function alterQueryStr($querystr, $param, $value) + { + $vars = preg_split('#&#', $querystr); + $set = FALSE; + + for ( $i = 0; $i < count($vars); $i++ ) + { + $v = preg_split('#=#', $vars[$i]); + + if ( $v[0] == $param ) + { + $v[1] = $value; + $vars[$i] = implode('=', $v); + $set = true; + break; + } + } + if ( !$set ) + { + $vars[] = "{$param}={$value}"; + } + return ltrim(implode('&', $vars), '&'); + } + + /** + * passVar() + * passes one variable as hidden input field (multiple fields for arrays) + * @see passRequestVars in varsx.x.x.php + * + * @param string $key + * @param string $value + * @return void + */ + function passVar($key, $value) + { + // array ? + if ( is_array($value) ) + { + for ( $i = 0; $i < sizeof($value); $i++ ) + { + passVar($key . '[' . $i . ']', $value[$i]); + } + return; + } + + // other values: do stripslashes if needed + echo '' . "\n"; + return; + } + + /** + * checkVars() + * + * @param string $variables + * @return void + */ + function checkVars($variables) + { + foreach ( $variables as $variable ) + { + if ( array_key_exists($variable, $_GET) + || array_key_exists($variable, $_POST) + || array_key_exists($variable, $_COOKIE) + || array_key_exists($variable, $_ENV) + || (session_id() !== '' && array_key_exists($variable, $_SESSION)) + || array_key_exists($variable, $_FILES) ) + { + die('Sorry. An error occurred.'); + } + } + return; + } + + /** + * sanitizeParams() + * Sanitize parameters such as $_GET and $_SERVER['REQUEST_URI'] etc. + * to avoid XSS. + * + * @param void + * @return void + */ + function sanitizeParams() + { + $array = array(); + $str = ''; + $frontParam = ''; + + // REQUEST_URI of $_SERVER + $str =& $_SERVER["REQUEST_URI"]; + serverStringToArray($str, $array, $frontParam); + sanitizeArray($array); + arrayToServerString($array, $frontParam, $str); + + // QUERY_STRING of $_SERVER + $str =& $_SERVER["QUERY_STRING"]; + serverStringToArray($str, $array, $frontParam); + sanitizeArray($array); + arrayToServerString($array, $frontParam, $str); + + // $_GET + convArrayForSanitizing($_GET, $array); + sanitizeArray($array); + revertArrayForSanitizing($array, $_GET); + + // $_REQUEST (only GET param) + convArrayForSanitizing($_REQUEST, $array); + sanitizeArray($array); + revertArrayForSanitizing($array, $_REQUEST); + + return; + } + + function _addInputTags(&$keys,$prefix='') + { + foreach ( $keys as $key=>$value ) + { + if ( $prefix ) + { + $key=$prefix.'['.$key.']'; + } + if ( is_array($value) ) + { + _addInputTags($value,$key); + } + else + { + if ( get_magic_quotes_gpc() ) + {$value=stripslashes($value); + } + if ( $key == 'ticket' ) + { + continue; + } + echo ''."\n"; + } + } + return; + } + + /** + * serverStringToArray() + * Convert the server string such as $_SERVER['REQUEST_URI'] + * to arry like arry['blogid']=1 and array['page']=2 etc. + * + * @param string $uri string + * @param string &$query_elements elements of query according to application/x-www-form-urlencoded + * @param string &$hier_part hierarchical part includes path + * + * NOTE: + * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax + * 3. Syntax Components + * http://www.ietf.org/rfc/rfc3986.txt + * + * Hypertext Markup Language - 2.0 + * 8.2.1. The form-urlencoded Media Type + * http://tools.ietf.org/html/rfc1866#section-8.2.1 + * + * $_SERVER > Language Reference > Predefined Variables > PHP Manual + * http://www.php.net/manual/en/reserved.variables.server.php + */ + function serverStringToArray($uri, &$query_elements, &$hier_part) + { + // init param + $query_elements = array(); + $hier_part = ""; + + // split hierarchical part, e.g. /index.php, query and fragment, e.g. blogid=1&page=2#section1 + if ( i18n::strpos($uri, "?") > 0 ) + { + list($hier_part, $query_and_fragment) = preg_split("#\?#", $uri, 2); + } + else + { + $query_and_fragment = $uri; + $hier_part = ''; + } + + // If there is no query like blogid=1&page=2, return + if ( i18n::strpos($uri, "=") == FALSE && !i18n::strlen($hier_part) ) + { + $hier_part = $uri; + return; + } + + $query_elements = preg_split("#&#", $query_and_fragment); + return; + } + + /** + * arrayToServerString() + * Convert array like array['blogid'] to server string + * such as $_SERVER['REQUEST_URI'] + * + * @param array $query_elements elements of query according to application/x-www-form-urlencoded + * @param string $hier_part hier-part defined in RFC3986 + * @param string &$uri return value + * @return void + * + * NOTE: + * RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax + * 3. Syntax Components + * http://www.ietf.org/rfc/rfc3986.txt + * + * Hypertext Markup Language - 2.0 + * 8.2.1. The form-urlencoded Media Type + * http://tools.ietf.org/html/rfc1866#section-8.2.1 + * + * $_SERVER > Language Reference > Predefined Variables > PHP Manual + * http://www.php.net/manual/en/reserved.variables.server.php + */ + function arrayToServerString($query_elements, $hier_part, &$uri) + { + if ( i18n::strpos($uri, "?") !== FALSE ) + { + $uri = $hier_part . "?"; + } + else + { + $uri = $hier_part; + } + if ( count($query_elements) > 0 ) + { + $uri .= implode("&", $query_elements); + } + return; + } + + /** + * sanitizeArray() + * Sanitize array parameters. + * This function checks both key and value. + * - check key if it inclues " (double quote), remove from array + * - check value if it includes \ (escape sequece), remove remaining string + * + * @param array &$array elements of query according to application/x-www-form-urlencoded + * @return void + */ + function sanitizeArray(&$array) + { + $excludeListForSanitization = array('query'); + + foreach ( $array as $k => $v ) + { + // split to key and value + list($key, $val) = preg_split("#=#", $v, 2); + if ( !isset($val) ) + { + continue; + } + + // when magic quotes is on, need to use stripslashes, + // and then addslashes + if ( get_magic_quotes_gpc() ) + { + $val = stripslashes($val); + } + + // note that we must use addslashes here because this function is called before the db connection is made + // and sql_real_escape_string needs a db connection + $val = addslashes($val); + + // if $key is included in exclude list, skip this param + if ( !in_array($key, $excludeListForSanitization) ) + { + // check value + if ( i18n::strpos($val, '\\') > 0 ) + { + list($val, $tmp) = preg_split('#\\\\#', $val); + } + + // remove control code etc. + $val = strtr($val, "\0\r\n<>'\"", " "); + + // check key + if ( preg_match('#\"#', $key) > 0 ) + { + unset($array[$k]); + continue; + } + + // set sanitized info + $array[$k] = sprintf("%s=%s", $key, $val); + } + } + return; + } + + /** + * convArrayForSanitizing() + * Convert array for sanitizeArray function + * + * @param string $src array to be sanitized + * @param array &$array array to be temporarily stored + * @return void + */ + function convArrayForSanitizing($src, &$array) + { + $array = array(); + foreach ( $src as $key => $val ) + { + if ( !key_exists($key, $_GET) ) + { + continue; + } + $array[] = sprintf("%s=%s", $key, $val); + continue; + } + return; + } + + /** + * revertArrayForSanitizing() + * Revert array after sanitizeArray function + * + * @param array $array element of query according to application/x-www-form-urlencoded + * @param array &$dst combination of key and value + * @return void + */ + function revertArrayForSanitizing($array, &$dst) + { + foreach ( $array as $v ) + { + list($key, $val) = preg_split("#=#", $v, 2); + $dst[$key] = $val; + continue; + } + return; + } + + /** ++>>>>>>> skinnable-master * decodePathInfo() * * @param string $virtualpath @@@ -1948,399 -1978,399 +3787,798 @@@ function decodePathInfo($virtualpath /** ++<<<<<<< HEAD + * redirect() + * Stops processing the request and redirects to the given URL. + * - no actual contents should have been sent to the output yet + * - the URL will be stripped of illegal or dangerous characters + * + * @param string $uri + * @return void + */ +function redirect($url) +{ + $url = preg_replace('#[^a-z0-9-~+_.?\#=&;,/:@%*]#i', '', $url); + header('Location: ' . $url); + exit; +} + +/** + * getBookmarklet() + * Returns the Javascript code for a bookmarklet that works on most modern browsers + * + * @param integer $blogid ID for weblog + * @return script to call Bookmarklet + */ +function getBookmarklet($blogid, $width=600, $height=500) +{ + global $CONF; + + $script = "Q='';" + . "x=document;" + . "y=window;" + . "if ( x.selection )" + . "{" + . " Q=x.selection.createRange().text;" + . "}" + . "else if ( y.getSelection )" + . "{" + . " Q=y.getSelection();" + . "}" + . "else if ( x.getSelection )" + . "{" + . " Q=x.getSelection();" + . "}" + . "wingm = window.open('{$CONF['AdminURL']}bookmarklet.php?blogid={$blogid}" + . " &logtext=' + encodeURIComponent(Q) +" + . " '&loglink=' + encodeURIComponent(x.location.href) +" + . " '&loglinktitle=' + encodeURIComponent(x.title)," + . " 'nucleusbm'," + . " 'scrollbars=yes,width={$width},height={$height},left=10,top=10,status=yes,resizable=yes');" + . "wingm.focus();"; + + return $script; +} + +/** + * cleanFileName() + * cleans filename of uploaded file for writing to file system + * + * @param string $str + * @return string $cleaned filename ready for use + */ +function cleanFileName($str) +{ + $str = strtolower($str); + $ext_point = i18n::strrpos($str,"."); + if ( $ext_point === FALSE ) + { + return FALSE; + } + $ext = i18n::substr($str,$ext_point,i18n::strlen($str)); + $str = i18n::substr($str,0,$ext_point); + + return preg_replace("#[^a-z0-9-]#", "_", $str) . $ext; +} + +/** + * use Notification class instead of this + * Deprecated since 4.0: + */ +function getMailFooter() +{ + NOTIFICATION::get_mail_footer(); +} +function isValidMailAddress($address) +{ + return NOTIFICATION::address_validation($address); +} +/** + * use Entity class instead of this + * Deprecated since 4.0: + */ +function highlight($text, $expression, $highlight) +{ + return Entity::highlight($text, $expression, $highlight); +} +function shorten($string, $maxlength, $suffix) +{ + return Entity::shorten($string, $maxlength, $suffix); +} +function stringStripTags ($string) +{ + return Entity::strip_tags($string); +} +function toAscii($string) +{ + return Entity::anchor_footnoting($string); +} +function stringToAttribute ($string) +{ + return Entity::hsc($string); +} +function stringToXML ($string) +{ + return Entity::hen($string); +} +function encode_desc($data) +{ + return Entity::hen($data); +} +/** + * Centralisation of the functions that deals with locales + * This functions is based on the old way to deal with languages + * Deprecated since 4.0: + */ +function getLanguageName() +{ + if( ($language = i18n::convert_locale_to_old_language_file_name(i18n::get_current_locale())) === FALSE ) + { + $language ='english'; + } + return $language; +} +function selectLanguage($language) +{ + global $DIR_LANG; + include($DIR_LANG . preg_replace('#[\\\\|/]#', '', $language) . '.php'); + return; +} +/** + * use i18n class instead of these + * Deprecated since 4.0 + */ +function checkLanguage($lang) +{ + return ( preg_match('#^(.+)_(.+)_(.+)$#', $lang) + || i18n::convert_old_language_file_name_to_locale($lang) ); +} +function formatDate($format, $timestamp, $default_format, &$blog) +{ + $offset = date('Z', $timestamp); + if ( $blog ) + { + $offset += $blog->getTimeOffset() * 3600; + } + return i18n::formatted_datetime($format, $timestamp, $offset, $default_format); +} + +/** + * use DB class instead of these + * Deprecated since 4.0 + */ +function quickQuery($query) +{ + $row = DB::getRow($query); + return $row['result']; +} +function mysqldate($timestamp) +{ + return DB::formatDateTime($timestamp); + } +/** + * Centralisation of the functions that generate links + * Deprecated since 4.0: + * Please use Link::FunctionName(...) instead + */ +function createItemLink($itemid, $extra = '') +{ + return Link::create_item_link($itemid, $extra); +} +function createMemberLink($memberid, $extra = '') +{ + return Link::create_member_link($memberid, $extra); +} +function createCategoryLink($catid, $extra = '') +{ + return Link::create_category_link($catid, $extra); +} +function createArchiveListLink($blogid = '', $extra = '') +{ + return Link::create_archivelist_link($blogid, $extra); +} +function createArchiveLink($blogid, $archive, $extra = '') +{ + return Link::create_archive_link($blogid, $archive, $extra); +} +function createBlogidLink($blogid, $params = '') +{ + return Link::create_blogid_link($blogid, $params = ''); +} +function createLink($type, $params) +{ + return Link::create_link($type, $params); +} +function createBlogLink($url, $params) +{ + return Link::create_blog_link($url, $params); +} +/** + * use ActionLog class instead of this + * Deprecated since 4.0 + */ +function addToLog($level, $msg) +{ + ActionLog::add($level, $msg); +} +/** + * use PHP's implement + * Deprecated since 4.0 + */ +function ifset(&$var) +{ + if ( isset($var) ) + { + return $var; + } + + return NULL; +} +/** + * use Manager::getPluginNameFromPid() instead of this + * Deprecated since 4.0 + */ +function getPluginNameFromPid($pid) +{ + global $manager; + return $manager->getPluginNameFromPid($pid); +} +/** + * use Manager::numberOfEventSubscribers() instead of this + * Deprecated since 4.0 + */ +function numberOfEventSubscribers($event) +{ + global $manager; + return $manager->getNumberOfSubscribers($event); +} + +/** + * PluginAdmin has already the alternative implement + * Deprecated since 4.0 + */ +function ticketForPlugin() +{ + global $CONF, $DIR_LIBS, $DIR_LOCALES, $DIR_PLUGINS, $manager, $member, $ticketforplugin; + + /* initialize */ + $ticketforplugin = array(); + $ticketforplugin['ticket'] = FALSE; + + /* Check if using plugin's php file. */ + $p_translated = serverVar('SCRIPT_FILENAME'); + + if (!file_exists($p_translated) ) + { + header("HTTP/1.0 404 Not Found"); + exit(''); + } + + // check whether this is plugin or not + $p_translated = str_replace('\\', '/', $p_translated); + $d_plugins = str_replace('\\', '/', $DIR_PLUGINS); + if ( i18n::strpos($p_translated, $d_plugins) !== 0 ) + { + return; + } + + // Solve the plugin php file or admin directory + $phppath = i18n::substr($p_translated, i18n::strlen($d_plugins) ); + // Remove the first "/" if exists. + $phppath = preg_replace('#^/#', '', $phppath); + // Remove the first "NP_" and the last ".php" if exists. + $path = preg_replace('#^NP_(.*)\.php$#', '$1', $phppath); + // Remove the "/" and beyond. + $path = preg_replace('#^([^/]*)/(.*)$#', '$1', $path); + + // Solve the plugin name. + $plugins = array(); + $query = sprintf('SELECT pfile FROM %s;', sql_table('plugin')); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $name = i18n::substr($row['pfile'], 3); + $plugins[strtolower($name)] = $name; + } + + $res->closeCursor(); + + if ( !array_key_exists($path, $plugins) ) + { + header("HTTP/1.0 404 Not Found"); + exit(''); + } + else + { + $plugin_name = $plugins[$path]; + } + + /* Return if not index.php */ + if ( ($phppath != strtolower($plugin_name) . '/') + && ($phppath != strtolower($plugin_name) . '/index.php') ) + { + return; + } + + /* Exit if not logged in. */ + if ( !$member->isLoggedIn() ) + { + exit('You aren\'t logged in.'); + } + + /* Check if this feature is needed (ie, if "$manager->checkTicket()" is not included in the script). */ + if ( $file = @file($p_translated) ) + { + $prevline = ''; + + foreach($file as $line) + { + if (preg_match('#[\$]manager([\s]*)[\-]>([\s]*)checkTicket([\s]*)[\(]#i', $prevline . $line) ) + { + return; + } + + $prevline = $line; + } + } + + /* Show a form if not valid ticket */ + if ( (i18n::strpos(serverVar('REQUEST_URI'), '?') !== FALSE + || serverVar('QUERY_STRING') + || strtoupper(serverVar('REQUEST_METHOD') ) == 'POST') + && !$manager->checkTicket() ) + { + $oPluginAdmin = new PluginAdmin($plugin_name); + $oPluginAdmin->start(); + + echo '

' . _ERROR_BADTICKET . "

\n"; + + // Resolve URI and QUERY_STRING + if ($uri = serverVar('REQUEST_URI') ) + { + list($uri, $qstring) = preg_split('#\?#', $uri); + } + else + { + if ( !($uri = serverVar('PHP_SELF') ) ) + { + $uri = serverVar('SCRIPT_NAME'); + } + $qstring = serverVar('QUERY_STRING'); + } + if ($qstring) + { + $qstring = '?' . $qstring; + } + + echo '

' . _SETTINGS_UPDATE . ' : ' . _QMENU_PLUGINS . ' ' . Entity::hsc($plugin_name) . " ?

\n"; + + switch(strtoupper(serverVar('REQUEST_METHOD') ) ) + { + case 'POST': + echo '
'; + $manager->addTicketHidden(); + _addInputTags($_POST); + break; + + case 'GET': + echo ''; + $manager->addTicketHidden(); + _addInputTags($_GET); + + default: + break; + } + + echo '    '; + echo ''; + echo "
\n"; + + $oPluginAdmin->end(); + exit; + } + + /* Create new ticket */ + $ticket=$manager->addTicketToUrl(''); + $ticketforplugin['ticket'] = preg_split($ticket, i18n::strpos($ticket, 'ticket=') + 7); + return; +} ++======= + * redirect() + * Stops processing the request and redirects to the given URL. + * - no actual contents should have been sent to the output yet + * - the URL will be stripped of illegal or dangerous characters + * + * @param string $uri + * @return void + */ + function redirect($url) + { + $url = preg_replace('#[^a-z0-9-~+_.?\#=&;,/:@%*]#i', '', $url); + header('Location: ' . $url); + exit; + } + + /** + * getBookmarklet() + * Returns the Javascript code for a bookmarklet that works on most modern browsers + * + * @param integer $blogid ID for weblog + * @return script to call Bookmarklet + */ + function getBookmarklet($blogid, $width=600, $height=500) + { + global $CONF; + + $script = "Q='';" + . "x=document;" + . "y=window;" + . "if ( x.selection )" + . "{" + . " Q=x.selection.createRange().text;" + . "}" + . "else if ( y.getSelection )" + . "{" + . " Q=y.getSelection();" + . "}" + . "else if ( x.getSelection )" + . "{" + . " Q=x.getSelection();" + . "}" + . "wingm = window.open('{$CONF['AdminURL']}bookmarklet.php?blogid={$blogid}" + . " &logtext=' + encodeURIComponent(Q) +" + . " '&loglink=' + encodeURIComponent(x.location.href) +" + . " '&loglinktitle=' + encodeURIComponent(x.title)," + . " 'nucleusbm'," + . " 'scrollbars=yes,width={$width},height={$height},left=10,top=10,status=yes,resizable=yes');" + . "wingm.focus();"; + + return $script; + } + + /** + * cleanFileName() + * cleans filename of uploaded file for writing to file system + * + * @param string $str + * @return string $cleaned filename ready for use + */ + function cleanFileName($str) + { + $str = strtolower($str); + $ext_point = i18n::strrpos($str,"."); + if ( $ext_point === FALSE ) + { + return FALSE; + } + $ext = i18n::substr($str,$ext_point,i18n::strlen($str)); + $str = i18n::substr($str,0,$ext_point); + + return preg_replace("#[^a-z0-9-]#", "_", $str) . $ext; + } + + /** + * use Notification class instead of this + * Deprecated since 4.0: + */ + function getMailFooter() + { + NOTIFICATION::get_mail_footer(); + } + function isValidMailAddress($address) + { + return NOTIFICATION::address_validation($address); + } + /** + * use Entity class instead of this + * Deprecated since 4.0: + */ + function highlight($text, $expression, $highlight) + { + return Entity::highlight($text, $expression, $highlight); + } + function shorten($string, $maxlength, $suffix) + { + return Entity::shorten($string, $maxlength, $suffix); + } + function stringStripTags ($string) + { + return Entity::strip_tags($string); + } + function toAscii($string) + { + return Entity::anchor_footnoting($string); + } + function stringToAttribute ($string) + { + return Entity::hsc($string); + } + function stringToXML ($string) + { + return Entity::hen($string); + } + function encode_desc($data) + { + return Entity::hen($data); + } + /** + * Centralisation of the functions that deals with locales + * This functions is based on the old way to deal with languages + * Deprecated since 4.0: + */ + function getLanguageName() + { + if( ($language = i18n::convert_locale_to_old_language_file_name(i18n::get_current_locale())) === FALSE ) + { + $language ='english'; + } + return $language; + } + function selectLanguage($language) + { + global $DIR_LANG; + include($DIR_LANG . preg_replace('#[\\\\|/]#', '', $language) . '.php'); + return; + } + /** + * use i18n class instead of these + * Deprecated since 4.0 + */ + function checkLanguage($lang) + { + return ( preg_match('#^(.+)_(.+)_(.+)$#', $lang) + || i18n::convert_old_language_file_name_to_locale($lang) ); + } + function formatDate($format, $timestamp, $default_format, &$blog) + { + $offset = date('Z', $timestamp); + if ( $blog ) + { + $offset += $blog->getTimeOffset() * 3600; + } + return i18n::formatted_datetime($format, $timestamp, $offset, $default_format); + } + + /** + * use DB class instead of these + * Deprecated since 4.0 + */ + function quickQuery($query) + { + $row = DB::getRow($query); + return $row['result']; + } + function mysqldate($timestamp) + { + return DB::formatDateTime($timestamp); + } + /** + * Centralisation of the functions that generate links + * Deprecated since 4.0: + * Please use Link::FunctionName(...) instead + */ + function createItemLink($itemid, $extra = '') + { + return Link::create_item_link($itemid, $extra); + } + function createMemberLink($memberid, $extra = '') + { + return Link::create_member_link($memberid, $extra); + } + function createCategoryLink($catid, $extra = '') + { + return Link::create_category_link($catid, $extra); + } + function createArchiveListLink($blogid = '', $extra = '') + { + return Link::create_archivelist_link($blogid, $extra); + } + function createArchiveLink($blogid, $archive, $extra = '') + { + return Link::create_archive_link($blogid, $archive, $extra); + } + function createBlogidLink($blogid, $params = '') + { + return Link::create_blogid_link($blogid, $params = ''); + } + function createLink($type, $params) + { + return Link::create_link($type, $params); + } + function createBlogLink($url, $params) + { + return Link::create_blog_link($url, $params); + } + /** + * use ActionLog class instead of this + * Deprecated since 4.0 + */ + function addToLog($level, $msg) + { + ActionLog::add($level, $msg); + } + /** + * use PHP's implement + * Deprecated since 4.0 + */ + function ifset(&$var) + { + if ( isset($var) ) + { + return $var; + } + + return NULL; + } + /** + * use Manager::getPluginNameFromPid() instead of this + * Deprecated since 4.0 + */ + function getPluginNameFromPid($pid) + { + global $manager; + return $manager->getPluginNameFromPid($pid); + } + /** + * use Manager::numberOfEventSubscribers() instead of this + * Deprecated since 4.0 + */ + function numberOfEventSubscribers($event) + { + global $manager; + return $manager->getNumberOfSubscribers($event); + } + + /** + * PluginAdmin has already the alternative implement + * Deprecated since 4.0 + */ + function ticketForPlugin() + { + global $CONF, $DIR_LIBS, $DIR_LOCALES, $DIR_PLUGINS, $manager, $member, $ticketforplugin; + + /* initialize */ + $ticketforplugin = array(); + $ticketforplugin['ticket'] = FALSE; + + /* Check if using plugin's php file. */ + $p_translated = serverVar('SCRIPT_FILENAME'); + + if (!file_exists($p_translated) ) + { + header("HTTP/1.0 404 Not Found"); + exit(''); + } + + // check whether this is plugin or not + $p_translated = str_replace('\\', '/', $p_translated); + $d_plugins = str_replace('\\', '/', $DIR_PLUGINS); + if ( i18n::strpos($p_translated, $d_plugins) !== 0 ) + { + return; + } + + // Solve the plugin php file or admin directory + $phppath = i18n::substr($p_translated, i18n::strlen($d_plugins) ); + // Remove the first "/" if exists. + $phppath = preg_replace('#^/#', '', $phppath); + // Remove the first "NP_" and the last ".php" if exists. + $path = preg_replace('#^NP_(.*)\.php$#', '$1', $phppath); + // Remove the "/" and beyond. + $path = preg_replace('#^([^/]*)/(.*)$#', '$1', $path); + + // Solve the plugin name. + $plugins = array(); + $query = sprintf('SELECT pfile FROM %s;', sql_table('plugin')); + $res = DB::getResult($query); + + foreach ( $res as $row ) + { + $name = i18n::substr($row['pfile'], 3); + $plugins[strtolower($name)] = $name; + } + + $res->closeCursor(); + + if ( !array_key_exists($path, $plugins) ) + { + header("HTTP/1.0 404 Not Found"); + exit(''); + } + else + { + $plugin_name = $plugins[$path]; + } + + /* Return if not index.php */ + if ( ($phppath != strtolower($plugin_name) . '/') + && ($phppath != strtolower($plugin_name) . '/index.php') ) + { + return; + } + + /* Exit if not logged in. */ + if ( !$member->isLoggedIn() ) + { + exit('You aren\'t logged in.'); + } + + /* Check if this feature is needed (ie, if "$manager->checkTicket()" is not included in the script). */ + if ( $file = @file($p_translated) ) + { + $prevline = ''; + + foreach($file as $line) + { + if (preg_match('#[\$]manager([\s]*)[\-]>([\s]*)checkTicket([\s]*)[\(]#i', $prevline . $line) ) + { + return; + } + + $prevline = $line; + } + } + + /* Show a form if not valid ticket */ + if ( (i18n::strpos(serverVar('REQUEST_URI'), '?') !== FALSE + || serverVar('QUERY_STRING') + || strtoupper(serverVar('REQUEST_METHOD') ) == 'POST') + && !$manager->checkTicket() ) + { + $oPluginAdmin = new PluginAdmin($plugin_name); + $oPluginAdmin->start(); + + echo '

' . _ERROR_BADTICKET . "

\n"; + + // Resolve URI and QUERY_STRING + if ($uri = serverVar('REQUEST_URI') ) + { + list($uri, $qstring) = preg_split('#\?#', $uri); + } + else + { + if ( !($uri = serverVar('PHP_SELF') ) ) + { + $uri = serverVar('SCRIPT_NAME'); + } + $qstring = serverVar('QUERY_STRING'); + } + if ($qstring) + { + $qstring = '?' . $qstring; + } + + echo '

' . _SETTINGS_UPDATE . ' : ' . _QMENU_PLUGINS . ' ' . Entity::hsc($plugin_name) . " ?

\n"; + + switch(strtoupper(serverVar('REQUEST_METHOD') ) ) + { + case 'POST': + echo '
'; + $manager->addTicketHidden(); + _addInputTags($_POST); + break; + + case 'GET': + echo ''; + $manager->addTicketHidden(); + _addInputTags($_GET); + + default: + break; + } + + echo '    '; + echo ''; + echo "
\n"; + + $oPluginAdmin->end(); + exit; + } + + /* Create new ticket */ + $ticket=$manager->addTicketToUrl(''); + $ticketforplugin['ticket'] = preg_split($ticket, i18n::strpos($ticket, 'ticket=') + 7); + return; + } ++>>>>>>> skinnable-master diff --combined nucleus/libs/i18n.php index 1b494ea,b8628eb..9f846df --- a/nucleus/libs/i18n.php +++ b/nucleus/libs/i18n.php @@@ -1,683 -1,684 +1,1370 @@@ ++<<<<<<< HEAD + $value ) + { + if ( !is_array($value) ) + { + $array[$key] = self::convert($value, $from, $to); + } + else + { + self::convert_array($array[$key]); + } + } + } + + return $array; + } + + /** + * i18n::strlen + * strlen wrapper + * + * @static + * @param string $string target string + * @return integer the number of letters + */ + static public function strlen($string) + { + $length = 0; + if ( self::$mode == 'iconv' ) + { + $length = iconv_strlen($string, self::$current_charset); + } + else if ( self::$mode == 'mbstring' ) + { + $length = mb_strlen($string, self::$current_charset); + } + else + { + $length = strlen($string); + } + return (integer) $length; + } + + /** + * i18n::strpos + * strpos wrapper + * + * @static + * @param string $haystack string to search + * @param string $needle string for search + * @param integer $offset the position from which the search should be performed. + * @return integer/FALSE the numeric position of the first occurrence of needle in haystack + */ + static public function strpos($haystack, $needle, $offset=0) + { + $position = 0; + if ( self::$mode == 'iconv' ) + { + $position = iconv_strpos($haystack, $needle, $offset, self::$current_charset); + } + else if ( self::$mode == 'mbstring' ) + { + $position = mb_strpos($haystack, $needle, $offset, self::$current_charset); + } + else + { + $position = strpos($haystack, $needle, $offset); + } + + if ( $position !== FALSE) + { + $position = (integer) $position; + } + return $position; + } + + /** + * i18n::strrpos + * strrpos wrapper + * + * @static + * @param string $haystack string to search + * @param string $needle string for search + * @return integer/FALSE the numeric position of the last occurrence of needle in haystack + */ + static public function strrpos ($haystack, $needle) + { + $position = 0; + if ( self::$mode == 'iconv' ) + { + $position = iconv_strrpos($haystack, $needle, self::$current_charset); + } + else if ( self::$mode == 'mbstring' ) + { + $position = mb_strrpos($haystack, $needle, 0, self::$current_charset); + } + else + { + $position = strrpos($haystack, $needle, 0); + } + + if ( $position !== FALSE) + { + $position = (integer) $position; + } + return $position; + } + + /** + * i18n::substr + * substr wrapper + * + * @static + * @param string $string string to be cut + * @param string $start the position of starting + * @param integer $length the length to be cut + * @return string the extracted part of string + */ + static public function substr($string, $start, $length=0) + { + $return = ''; + + if ( $length == 0 ) + { + $length = self::strlen($string) - $start; + } + + if ( self::$mode == 'iconv' ) + { + $return = iconv_substr($string, $start, $length, self::$current_charset); + } + else if ( self::$mode == 'mbstring' ) + { + $return = mb_substr($string, $start, $length, self::$current_charset); + } + else + { + $return = strrpos($string, $start, $length); + } + return (string) $return; + } + + /** + * i18n::strftime + * strftime function based on multibyte processing + * + * @static + * @param string $format format with singlebyte or multibyte + * @param timestamp $timestamp UNIX timestamp + * @return string formatted timestamp + */ + static public function strftime($format, $timestamp='') + { + return preg_replace_callback('/(%[a-z%])/i', + create_function('$matches', 'return strftime($matches[1], ' . intval($timestamp) . ');'), + $format + ); + } + + /** + * i18n::formatted_datetime() + * return formatted datetime string + * + * Date and Time Formats + * @link http://www.w3.org/TR/NOTE-datetime + * + * Working with Time Zones + * @link http://www.w3.org/TR/timezone/ + * + * @param String $format time expression format + * @param String $timestamp UNIX timestamp + * @param Integer $offset timestamp offset + * @return String formatted datetime + */ + static public function formatted_datetime($format, $timestamp, $offset=0) + { + $suffix = ''; + $string = ''; + + switch ( $format ) + { + case 'mysql': + /* + * MySQL 5.0 Reference Manual + * 10.3.1. The DATE, DATETIME, and TIMESTAMP Types + * http://dev.mysql.com/doc/refman/5.0/en/datetime.html + */ + $timestamp += $offset; + $format = '%Y-%m-%d %H:%M:%S'; + $suffix =''; + break; + case 'rfc822': + /* + * RFC 822: STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES + * 5. DATE AND TIME SPECIFICATION + * http://www.ietf.org/rfc/rfc0822.txt + */ + $format = '%a, %d %m %y %H:%M:%S '; + if ( $offset < 0 ) + { + $suffix = '-'; + $offset = -$offset; + } + else + { + $suffix = '+'; + } + + $suffix .= sprintf("%02d%02d", floor($offset / 3600), round(($offset % 3600) / 60) ); + break; + case 'rfc822GMT': + /* + * RFC 822: STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES + * 5. DATE AND TIME SPECIFICATION + * http://www.ietf.org/rfc/rfc0822.txt + */ + $format = '%a, %d %m %y %H:%M:%S '; + $timestamp -= $offset; + $suffix = 'GMT'; + break; + case 'iso8601': + case 'rfc3339': + /* + * RFC3339: Date and Time on the Internet: Timestamps + * 5. Date and Time format + * http://www.ietf.org/rfc/rfc3339.txt + */ + $format = '%Y-%m-%dT%H:%M:%S'; + if ( $offset < 0 ) + { + $suffix = '-'; + $offset = -$offset; + } + else + { + $suffix = '+'; + } + $suffix .= sprintf("%02d:%02d", floor($offset / 3600), round(($offset % 3600) / 60) ); + break; + case 'utc': + case 'iso8601UTC': + case 'rfc3339UTC': + /* + * RFC3339: Date and Time on the Internet: Timestamps + * 5. Date and Time format + * http://www.ietf.org/rfc/rfc3339.txt + */ + $timestamp -= $offset; + $format = '%Y-%m-%dT%H:%M:%SZ'; + $suffix = ''; + break; + case '': + $format = '%X %x'; + $offset = ''; + break; + default: + $suffix = ''; + break; + } + return i18n::strftime($format, $timestamp) . $suffix; + } + + /** + * i18n::convert_locale_to_old_language_file_name() + * NOTE: this should be obsoleted near future. + * + * @static + * @param string $target_locale locale name as language_script_region + * @return string old translation file name + */ + static public function convert_locale_to_old_language_file_name($target_locale) + { + $target_language = ''; + foreach ( self::$lang_refs as $language => $locale ) + { + if ( preg_match('#-#', $language) ) + { + if ( $target_locale . '.' . self::$current_charset == $locale ) + { + $target_language = $language; + break; + } + } + else if ( $target_locale == $locale ) + { + $target_language = $language; + } + } + return $target_language; + } + + /** + * i18n::convert_old_language_file_name_to_locale() + * NOTE: this should be obsoleted near future. + * + * @static + * @param string $target_language old translation file name + * @return string locale name as language_script_region + */ + static public function convert_old_language_file_name_to_locale($target_language) + { + $target_locale = ''; + foreach ( self::$lang_refs as $language => $locale ) + { + if ( $target_language == $language ) + { + if ( preg_match('#^(.+)\.(.+)$#', $locale, $match) ) + { + $target_locale = $match[1]; + } + else + { + $target_locale = $locale; + } + break; + } + } + return $target_locale; + } + + /** + * i18n::$lang_refs + * reference table to convert old and new way to name translation files. + * NOTE: this should be obsoleted as soon as possible. + * + * @static + */ + static private $lang_refs = array( + "english" => "en_Latn_US", + "english-utf8" => "en_Latn_US.UTF-8", + "bulgarian" => "bg_Cyrl_BG", + "finnish" => "fi_Latn_FU", + "catalan" => "ca_Latn_ES", + "french" => "fr_Latn_FR", + "russian" => "ru_Cyrl_RU", + "chinese" => "zh_Hans_CN", + "simchinese" => "zh_Hans_CN", + "chineseb5" => "zh_Hant_TW", + "traditional_chinese" => "zh_Hant_TW", + "galego" => "gl_Latn_ES", + "german" => "de_Latn_DE", + "korean-utf" => "ko_Kore_KR.UTF-8", + "korean-euc-kr" => "ko_Kore_KR.EUC-KR", + "slovak" => "sk_Latn_SK", + "czech" => "cs_Latn_CZ", + "hungarian" => "hu_Latn_HU", + "latvian" => "lv_Latn_LV", + "nederlands" => "nl_Latn_NL", + "italiano" => "it_Latn_IT", + "persian" => "fa_Arab_IR", + "spanish" => "es_Latn_ES", + "spanish-utf8" => "es_Latn_ES.UTF-8", + "japanese-euc" => "ja_Jpan_JP.EUC-JP", + "japanese-utf8" => "ja_Jpan_JP.UTF-8", + "portuguese_brazil" => "pt_Latn_BR" + ); +} ++======= + $value ) + { + if ( !is_array($value) ) + { + $array[$key] = self::convert($value, $from, $to); + } + else + { + self::convert_array($array[$key]); + } + } + } + + return $array; + } + + /** + * i18n::strlen + * strlen wrapper + * + * @static + * @param string $string target string + * @return integer the number of letters + */ + static public function strlen($string) + { + $length = 0; + if ( self::$mode == 'iconv' ) + { + $length = iconv_strlen($string, self::$current_charset); + } + else if ( self::$mode == 'mbstring' ) + { + $length = mb_strlen($string, self::$current_charset); + } + else + { + $length = strlen($string); + } + return (integer) $length; + } + + /** + * i18n::strpos + * strpos wrapper + * + * @static + * @param string $haystack string to search + * @param string $needle string for search + * @param integer $offset the position from which the search should be performed. + * @return integer/FALSE the numeric position of the first occurrence of needle in haystack + */ + static public function strpos($haystack, $needle, $offset=0) + { + $position = 0; + if ( self::$mode == 'iconv' ) + { + $position = iconv_strpos($haystack, $needle, $offset, self::$current_charset); + } + else if ( self::$mode == 'mbstring' ) + { + $position = mb_strpos($haystack, $needle, $offset, self::$current_charset); + } + else + { + $position = strpos($haystack, $needle, $offset); + } + + if ( $position !== FALSE) + { + $position = (integer) $position; + } + return $position; + } + + /** + * i18n::strrpos + * strrpos wrapper + * + * @static + * @param string $haystack string to search + * @param string $needle string for search + * @return integer/FALSE the numeric position of the last occurrence of needle in haystack + */ + static public function strrpos ($haystack, $needle) + { + $position = 0; + if ( self::$mode == 'iconv' ) + { + $position = iconv_strrpos($haystack, $needle, self::$current_charset); + } + else if ( self::$mode == 'mbstring' ) + { + $position = mb_strrpos($haystack, $needle, 0, self::$current_charset); + } + else + { + $position = strrpos($haystack, $needle, 0); + } + + if ( $position !== FALSE) + { + $position = (integer) $position; + } + return $position; + } + + /** + * i18n::substr + * substr wrapper + * + * @static + * @param string $string string to be cut + * @param string $start the position of starting + * @param integer $length the length to be cut + * @return string the extracted part of string + */ + static public function substr($string, $start, $length=0) + { + $return = ''; + + if ( $length == 0 ) + { + $length = self::strlen($string) - $start; + } + + if ( self::$mode == 'iconv' ) + { + $return = iconv_substr($string, $start, $length, self::$current_charset); + } + else if ( self::$mode == 'mbstring' ) + { + $return = mb_substr($string, $start, $length, self::$current_charset); + } + else + { + $return = strrpos($string, $start, $length); + } + return (string) $return; + } + + /** + * i18n::strftime + * strftime function based on multibyte processing + * + * @static + * @param string $format format with singlebyte or multibyte + * @param timestamp $timestamp UNIX timestamp + * @return string formatted timestamp + */ + static public function strftime($format, $timestamp='') + { + return preg_replace_callback('/(%[a-z%])/i', + create_function('$matches', 'return strftime($matches[1], ' . intval($timestamp) . ');'), + $format + ); + } + + /** + * i18n::formatted_datetime() + * return formatted datetime string + * + * Date and Time Formats + * @link http://www.w3.org/TR/NOTE-datetime + * + * Working with Time Zones + * @link http://www.w3.org/TR/timezone/ + * + * @param String $format time expression format + * @param String $timestamp UNIX timestamp + * @param Integer $offset timestamp offset + * @return String formatted datetime + */ + static public function formatted_datetime($format, $timestamp, $offset=0) + { + $suffix = ''; + $string = ''; + + switch ( $format ) + { + case 'mysql': + /* + * MySQL 5.0 Reference Manual + * 10.3.1. The DATE, DATETIME, and TIMESTAMP Types + * http://dev.mysql.com/doc/refman/5.0/en/datetime.html + */ + $timestamp += $offset; + $format = '%Y-%m-%d %H:%M:%S'; + $suffix =''; + break; + + case 'rfc822': + /* + * RFC 822: STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES + * 5. DATE AND TIME SPECIFICATION + * http://www.ietf.org/rfc/rfc0822.txt + */ + $format = '%a, %d %m %y %H:%M:%S '; + if ( $offset < 0 ) + { + $suffix = '-'; + $offset = -$offset; + } + else + { + $suffix = '+'; + } + + $suffix .= sprintf("%02d%02d", floor($offset / 3600), round(($offset % 3600) / 60) ); + break; + case 'rfc822GMT': + /* + * RFC 822: STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES + * 5. DATE AND TIME SPECIFICATION + * http://www.ietf.org/rfc/rfc0822.txt + */ + $format = '%a, %d %m %y %H:%M:%S '; + $timestamp -= $offset; + $suffix = 'GMT'; + break; + case 'iso8601': + case 'rfc3339': + /* + * RFC3339: Date and Time on the Internet: Timestamps + * 5. Date and Time format + * http://www.ietf.org/rfc/rfc3339.txt + */ + $format = '%Y-%m-%dT%H:%M:%S'; + if ( $offset < 0 ) + { + $suffix = '-'; + $offset = -$offset; + } + else + { + $suffix = '+'; + } + $suffix .= sprintf("%02d:%02d", floor($offset / 3600), round(($offset % 3600) / 60) ); + break; + case 'utc': + case 'iso8601UTC': + case 'rfc3339UTC': + /* + * RFC3339: Date and Time on the Internet: Timestamps + * 5. Date and Time format + * http://www.ietf.org/rfc/rfc3339.txt + */ + $timestamp -= $offset; + $format = '%Y-%m-%dT%H:%M:%SZ'; + $suffix = ''; + break; + case '': + $format = '%X %x'; + $offset = ''; + break; + default: + $suffix = ''; + break; + } + return i18n::strftime($format, $timestamp) . $suffix; + } + + /** + * i18n::convert_locale_to_old_language_file_name() + * NOTE: this should be obsoleted near future. + * + * @static + * @param string $target_locale locale name as language_script_region + * @return string old translation file name + */ + static public function convert_locale_to_old_language_file_name($target_locale) + { + $target_language = ''; + foreach ( self::$lang_refs as $language => $locale ) + { + if ( preg_match('#-#', $language) ) + { + if ( $target_locale . '.' . self::$current_charset == $locale ) + { + $target_language = $language; + break; + } + } + else if ( $target_locale == $locale ) + { + $target_language = $language; + } + } + return $target_language; + } + + /** + * i18n::convert_old_language_file_name_to_locale() + * NOTE: this should be obsoleted near future. + * + * @static + * @param string $target_language old translation file name + * @return string locale name as language_script_region + */ + static public function convert_old_language_file_name_to_locale($target_language) + { + $target_locale = ''; + foreach ( self::$lang_refs as $language => $locale ) + { + if ( $target_language == $language ) + { + if ( preg_match('#^(.+)\.(.+)$#', $locale, $match) ) + { + $target_locale = $match[1]; + } + else + { + $target_locale = $locale; + } + break; + } + } + return $target_locale; + } + + /** + * i18n::$lang_refs + * reference table to convert old and new way to name translation files. + * NOTE: this should be obsoleted as soon as possible. + * + * @static + */ + static private $lang_refs = array( + "english" => "en_Latn_US", + "english-utf8" => "en_Latn_US.UTF-8", + "bulgarian" => "bg_Cyrl_BG", + "finnish" => "fi_Latn_FI", + "catalan" => "ca_Latn_ES", + "french" => "fr_Latn_FR", + "russian" => "ru_Cyrl_RU", + "chinese" => "zh_Hans_CN", + "simchinese" => "zh_Hans_CN", + "chineseb5" => "zh_Hant_TW", + "traditional_chinese" => "zh_Hant_TW", + "galego" => "gl_Latn_ES", + "german" => "de_Latn_DE", + "korean-utf" => "ko_Kore_KR.UTF-8", + "korean-euc-kr" => "ko_Kore_KR.EUC-KR", + "slovak" => "sk_Latn_SK", + "czech" => "cs_Latn_CZ", + "hungarian" => "hu_Latn_HU", + "latvian" => "lv_Latn_LV", + "nederlands" => "nl_Latn_NL", + "italiano" => "it_Latn_IT", + "persian" => "fa_Arab_IR", + "spanish" => "es_Latn_ES", + "spanish-utf8" => "es_Latn_ES.UTF-8", + "japanese-euc" => "ja_Jpan_JP.EUC-JP", + "japanese-utf8" => "ja_Jpan_JP.UTF-8", + "portuguese_brazil" => "pt_Latn_BR" + ); + } ++>>>>>>> skinnable-master diff --combined nucleus/libs/showlist.php index 8fcbccc,bc687f2..a0eaba9 --- a/nucleus/libs/showlist.php +++ b/nucleus/libs/showlist.php @@@ -14,264 -14,505 +14,764 @@@ * * @license http://nucleuscms.org/license.txt GNU General Public License * @copyright Copyright (C) 2002-2009 The Nucleus Group ++<<<<<<< HEAD + * @version $Id: showlist.php 1785 2012-04-22 11:25:14Z sakamocchi $ ++======= + * @version $Id: showlist.php 1886 2012-06-17 08:27:27Z sakamocchi $ ++>>>>>>> skinnable-master */ // can take either an array of objects, or an SQL query ++<<<<<<< HEAD +function showlist($query, $type, $template) +{ + if ( is_array($query) ) + { + if ( sizeof($query) == 0 ) + { + return 0; + } + + call_user_func("listplug_{$type}", $template, 'HEAD'); + + foreach ( $query as $currentObj ) + { + $template['current'] = $currentObj; + call_user_func("listplug_{$type}", $template, 'BODY'); + } + + call_user_func("listplug_{$type}", $template, 'FOOT'); + + return sizeof($query); + } + else + { + $res = DB::getResult($query); + + // don't do anything if there are no results + $numrows = $res->rowCount(); + if ( $numrows == 0 ) + { + return 0; + } + call_user_func("listplug_{$type}", $template, 'HEAD'); + + foreach ( $res as $row ) + { + $template['current'] = $row; + call_user_func("listplug_{$type}", $template, 'BODY'); + } + + call_user_func("listplug_{$type}", $template, 'FOOT'); + + $res->closeCursor(); + + // return amount of results + return $numrows; + } +} + +function listplug_select($template, $type) +{ + switch( $type ) + { + case 'HEAD': + echo "'; + break; + } + return; +} + +function listplug_table($template, $type) +{ + switch( $type ) + { + case 'HEAD': + echo "\n\n"; + echo "\n"; + echo "\n"; + echo "\n"; + // print head + call_user_func("listplug_table_{$template['content']}" , $template, 'HEAD'); + echo "\n"; + echo "\n"; + echo "\n"; + break; + case 'BODY': + // print tabletype specific thingies + echo "\n"; + call_user_func("listplug_table_{$template['content']}" , $template, 'BODY'); + echo "\n"; + break; + case 'FOOT': + call_user_func("listplug_table_{$template['content']}" , $template, 'FOOT'); + echo "\n"; + echo "
\n"; + echo "\n"; + break; + } + return; +} + +function listplug_table_memberlist($template, $type) +{ + switch( $type ) + { + case 'HEAD': + echo '' . _LIST_MEMBER_NAME . "\n"; + echo '' . _LIST_MEMBER_RNAME . "\n"; + echo '' . _LIST_MEMBER_URL . "\n"; + echo '' . _LIST_MEMBER_ADMIN; + help('superadmin'); + echo "\n"; + echo '' . _LIST_MEMBER_LOGIN; + help('canlogin'); + echo "\n"; + echo '' . _LISTS_ACTIONS. "\n"; + break; + case 'BODY': + $current = $template['current']; + echo ''; + $id = listplug_nextBatchId(); + echo "\n"; + echo "
' . Entity::hsc($current['mname']), "\n"; + echo "\n"; + echo ""; + echo "" . Entity::hsc($current['mrealname']) . "\n"; + echo '' . Entity::hsc($current['murl']) . "\n"; + echo '' . ($current['madmin'] ? _YES : _NO) . "\n"; + echo '' . ($current['mcanlogin'] ? _YES : _NO) . "\n"; + echo '' . _LISTS_EDIT . "\n"; + echo '' . _LISTS_DELETE . "\n"; + break; + } + return; +} + +function listplug_table_teamlist($template, $type) +{ + global $manager; + switch( $type ) + { + case 'HEAD': + echo "" . _LIST_MEMBER_NAME . "\n"; + echo "" . _LIST_MEMBER_RNAME . "\n"; + echo "" . _LIST_TEAM_ADMIN; + help('teamadmin'); + echo "\n"; + echo ""._LISTS_ACTIONS."\n"; + break; + case 'BODY': + $current = $template['current']; + + echo ''; + $id = listplug_nextBatchId(); + echo "\n"; + echo '\n"; + echo ""; + echo '', Entity::hsc($current['mrealname']), "\n"; + echo '', ($current['tadmin'] ? _YES : _NO) , "\n"; + echo '' . _LISTS_DELETE . "\n"; + + $url = "index.php?action=teamchangeadmin&memberid={$current['tmember']}&blogid={$current['tblog']}"; + $url = $manager->addTicketToUrl($url); + echo '' . _LIST_TEAM_CHADMIN . "\n"; + break; + } + return; +} + +function listplug_table_pluginlist($template, $type) +{ + global $manager; + switch( $type ) + { + case 'HEAD': + echo '' . _LISTS_INFO . "\n"; + echo '' . _LISTS_DESC . "\n"; + echo '' . _LISTS_ACTIONS . "\n"; + break; + case 'BODY': + $current = $template['current']; ++======= + function showlist($query, $type, $vars, $template_name = '') + { + $contents = ''; + + /* count */ + if ( is_string($query) ) + { + $resource = DB::getResult($query); + } + else + { + $resource = $query; + } + + /* HEAD */ + $contents .= call_user_func("listplug_{$type}", $vars, 'HEAD', $template_name); + + /* BODY */ + foreach ( $resource as $row ) + { + $vars['current'] = $row; + $contents .= call_user_func("listplug_{$type}", $vars, 'BODY', $template_name); + } + + /* FOOT */ + $contents .= call_user_func("listplug_{$type}", $vars, 'FOOT', $template_name); + + /* close SQL resource */ + if ( is_string($query) ) + { + $resource->closeCursor(); + } + + return $contents; + } + + function listplug_select($vars, $type, $template_name = '') + { + global $manager; + + $templates = array(); + if ( !empty($template_name) ) + { + $templates =& $manager->getTemplate($template_name); + } + + switch( $type ) + { + case 'HEAD': + if ( !array_key_exists('SHOWLIST_LISTPLUG_SELECT_HEAD', $templates) || empty($templates['SHOWLIST_LISTPLUG_SELECT_HEAD']) ) + { + $template = "\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_SELECT_FOOT']; + } + $data = array(); + break; + } + + return Template::fill($template, $data); + } + + function listplug_table($vars, $type, $template_name = '') + { + global $manager; + + $templates = array(); + if ( !empty($template_name) ) + { + $templates =& $manager->getTemplate($template_name); + } + + switch( $type ) + { + case 'HEAD': + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_HEAD', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_HEAD']) ) + { + $template = "\n" + . "\n" + . "\n" + . "<%typehead%>\n" + . "\n" + . "\n" + . "\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_HEAD']; + } + $data = array( + 'summary' => $vars['content'], + 'typehead' => call_user_func("listplug_table_" . $vars['content'] , $vars, 'HEAD', $template_name) + ); + break; + case 'BODY': + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_BODY', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_BODY']) ) + { + $template = "\n" + . "<%typebody%>\n" + . "\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_BODY']; + } + // tabletype specific thingies + $data = array( + 'typebody' => call_user_func("listplug_table_" . $vars['content'] , $vars, 'BODY', $template_name) + ); + break; + case 'FOOT': + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_FOOT', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_FOOT']) ) + { + $template = "<%typefoot%>\n" + . "\n" + . "
\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_FOOT']; + } + // tabletype specific thingies + $data = array( + 'typefoot' => call_user_func("listplug_table_" . $vars['content'] , $vars, 'FOOT', $template_name) + ); + break; + } + + return Template::fill($template, $data); + } + + function listplug_table_memberlist($vars, $type, $template_name = '') + { + global $manager; + + $templates = array(); + if ( !empty($template_name) ) + { + $templates =& $manager->getTemplate($template_name); + } + + switch( $type ) + { + case 'HEAD': + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_MEMBLIST_HEAD', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_MEMBLIST_HEAD']) ) + { + $template = "<%colmembername%>\n" + . "<%colmemberrname%>\n" + . "<%colmemberurl%>\n" + . "<%colmemberadmin%><%helplink(superadmin)%>\n" + . "<%colmemberlogin%><%helplink(canlogin)%>\n" + . "<%colactions%>\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_MEMBLIST_HEAD']; + } + $data = array( + 'colmembername' => _LIST_MEMBER_NAME, + 'colmemberrname' => _LIST_MEMBER_RNAME, + 'colmemberurl' => _LIST_MEMBER_URL, + 'colmemberadmin' => _LIST_MEMBER_ADMIN, + 'colmemberlogin' => _LIST_MEMBER_LOGIN, + 'colactions' => _LISTS_ACTIONS, + ); + break; + case 'BODY': + $current = $vars['current']; + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_MEMBLIST_BODY', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_MEMBLIST_BODY']) ) + { + $template = "\n" + . "\" name=\"batch[<%id%>]\" value=\"<%memberid%>\" />\n" + . "\n\n" + . "<%realname%>\n" + . "\" tabindex=\"<%tabindex%>\"><%url%>\n" + . "<%admin%>\n" + . "<%login%>\n" + . "\" tabindex=\"<%tabindex%>\"><%editbtn%>\n" + . "\" tabindex=\"<%tabindex%>\"><%deletebtn%>\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_MEMBLIST_BODY']; + } + $data = array( + 'id' => listplug_nextBatchId(), + 'memberid' => $current['mnumber'], + 'mailaddress' => Entity::hsc($current['memail']), + 'tabindex' => $vars['tabindex'], + 'name' => Entity::hsc($current['mname']), + 'realname' => Entity::hsc($current['mrealname']), + 'url' => Entity::hsc($current['murl']), + 'admin' => $current['madmin'] ? _YES : _NO, + 'login' => $current['mcanlogin'] ? _YES : _NO, + 'editbtn' => _LISTS_EDIT, + 'deletebtn' => _LISTS_DELETE, + ); + break; + case 'FOOT': + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_MEMBLIST_FOOT', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_MEMBLIST_FOOT']) ) + { + $template = ""; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_MEMBLIST_FOOT']; + } + $data = array(); + break; + } + return Template::fill($template, $data); + } + + function listplug_table_teamlist($vars, $type, $template_name = '') + { + global $manager; + + $templates = array(); + if ( !empty($template_name) ) + { + $templates =& $manager->getTemplate($template_name); + } + + switch( $type ) + { + case 'HEAD': + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_TEAMLIST_HEAD', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_TEAMLIST_HEAD']) ) + { + $template = "<%colmembername%>\n" + . "<%colmemberrname%>\n" + . "<%colteamadmin%><%helplink(teamadmin)%>\n" + . "<%colactions%>\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_TEAMLIST_HEAD']; + } + $data = array( + 'colmembername' => _LIST_MEMBER_NAME, + 'colmemberrname' => _LIST_MEMBER_RNAME, + 'colteamadmin' => _LIST_TEAM_ADMIN, + 'colactions' => _LISTS_ACTIONS, + ); + break; + case 'BODY': + $current = $vars['current']; + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_TEAMLIST_BODY', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_TEAMLIST_BODY']) ) + { + $template = "\n" + . "\" name=\"batch[<%id%>]\" value=\"<%memberid%>\" />\n" + . "\n\n" + . "<%realname%>\n" + . "<%admin%>\n" + . "&blogid=<%blogid%>\" tabindex=\"<%tabindex%>\"><%deletebtn%>\n" + . "\" tabindex=\"<%tabindex%>\"><%chadminbtn%>\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_TEAMLIST_BODY']; + } + $url = 'index.php?action=teamchangeadmin&memberid=' . intval($current['tmember']) . '&blogid=' . intval($current['tblog']); + $url = $manager->addTicketToUrl($url); + $data = array( + 'id' => listplug_nextBatchId(), + 'memberid' => $current['tmember'], + 'mailaddress' => Entity::hsc($current['memail']), + 'tabindex' => $vars['tabindex'], + 'name' => Entity::hsc($current['mname']), + 'realname' => Entity::hsc($current['mrealname']), + 'admin' => ($current['tadmin'] ? _YES : _NO), + 'blogid' => $current['tblog'], + 'deletebtn' => '<%text(_LISTS_DELETE)%>', + 'chadminurl' => Entity::hsc($url), + 'chadminbtn' => '<%text(_LIST_TEAM_CHADMIN)%>' + ); + break; + case 'FOOT': + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_TEAMLIST_FOOT', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_TEAMLIST_FOOT']) ) + { + $template = ""; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_TEAMLIST_FOOT']; + } + $data = array(); + break; + } + return Template::fill($template, $data); + } + + function listplug_table_pluginlist($vars, $type, $template_name = '') + { + static $plugins = array(); + global $manager; + + $templates = array(); + if ( !empty($template_name) ) + { + $templates =& $manager->getTemplate($template_name); + } + + switch( $type ) + { + case 'HEAD': + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_PLUGLIST_HEAD', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_PLUGLIST_HEAD']) ) + { + $template = "<%colinfo%>\n" + . "<%coldesc%>\n" + . "<%colactions%>\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_PLUGLIST_HEAD']; + } + $data = array( + 'colinfo' => _LISTS_INFO, + 'coldesc' => _LISTS_DESC, + 'colactions' => _LISTS_ACTIONS, + ); + break; + case 'BODY': + $current = $vars['current']; ++>>>>>>> skinnable-master $plug =& $manager->getPlugin($current['pfile']); if ( $plug ) { ++<<<<<<< HEAD + echo "\n"; + echo '

' . Entity::hsc($plug->getName()) . "

\n"; + + echo "
\n"; + if ( $plug->getAuthor() ) + { + echo '
' . _LIST_PLUGS_AUTHOR . "
\n"; + echo '
' . Entity::hsc($plug->getAuthor()) , "
\n"; + } + + if ( $plug->getVersion() ) + { + echo '
' . _LIST_PLUGS_VER, "
\n"; + echo '
' . Entity::hsc($plug->getVersion()) . "
\n"; + } + + if ( $plug->getURL() ) + { + echo '
' . _LIST_PLUGS_SITE . "
\n"; + echo '
リンク
' . "\n"; + } + echo "
\n"; + echo "\n"; + + echo "\n"; + echo "
\n"; + echo '
' . _LIST_PLUGS_DESC ."
\n"; + echo '
' . Entity::hen($plug->getDescription()) ."
\n"; + if ( sizeof($plug->getEventList()) > 0 ) + { + echo '
' . _LIST_PLUGS_SUBS ."
\n"; + echo '
' . Entity::hsc(implode(', ', $plug->getEventList())) ."
\n"; + } + + if ( sizeof($plug->getPluginDep()) > 0 ) + { + echo '
' . _LIST_PLUGS_DEP ."
\n"; + echo '
' . Entity::hsc(implode(', ', $plug->getPluginDep())) ."
\n"; + } + + /* check dependency */ + $req = array(); + $res = DB::getResult('SELECT pfile FROM ' . sql_table('plugin')); + foreach ( $res as $row ) + { + $preq =& $manager->getPlugin($row['pfile']); ++======= + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_PLUGLIST_BODY', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_PLUGLIST_BODY']) ) + { + $template = "\n" + . "<%plugname%>
\n" + . "<%autherlabel%> <%plugauther%>
\n" + . "<%versionlabel%> <%plugversion%>
\n" + . "<%pluggeturl%>
\n" + . "\n" + . "\n" + . "<%desclabel%>
<%plugdesc%>\n" + . "<%eventlist%>\n" + . "<%needupdate%>\n" + . "<%dependlist%>\n" + . "<%depreqlist%>\n" + . "\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_PLUGLIST_BODY']; + } + $data = array( + 'plugname' => Entity::hsc($plug->getName()), + 'autherlabel' => _LIST_PLUGS_AUTHOR, + 'plugauther' => Entity::hsc($plug->getAuthor()), + 'versionlabel' => _LIST_PLUGS_VER, + 'plugversion' => Entity::hsc($plug->getVersion()), + 'tabindex' => $vars['tabindex'], + 'desclabel' => _LIST_PLUGS_DESC, + 'plugdesc' => Entity::hen($plug->getDescription()), + ); + if ( $plug->getURL() ) + { + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_PLUGLIST_GURL', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_PLUGLIST_GURL']) ) + { + $subTpl = "\" tabindex=\"<%tabindex%>\"><%plugsite%>"; + } + else + { + $subTpl = $templates['SHOWLIST_LISTPLUG_TABLE_PLUGLIST_GURL']; + } + $subData = array( + 'plugurl' => Entity::hsc($plug->getURL()), + 'tabindex' => $vars['tabindex'], + 'plugsite' => _LIST_PLUGS_SITE, + ); + $data['pluggeturl'] = Template::fill($subTpl, $subData); + } + else + { + $data['pluggeturl'] = ''; + } + if ( count($plug->getEventList()) > 0 ) + { + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_PLUGEVENTLIST', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_PLUGEVENTLIST']) ) + { + $subTpl = "

<%evntlstlbl%>
<%eventlist%>"; + } + else + { + $subTpl = $templates['SHOWLIST_LISTPLUG_TABLE_PLUGEVENTLIST']; + } + $subData = array( + 'evntlstlbl' => _LIST_PLUGS_SUBS, + 'eventlist' => Entity::hsc(implode(', ', $plug->getEventList())), + ); + $data['eventlist'] = Template::fill($subTpl, $subData); + } + else + { + $data['eventlist'] = ''; + } + if ( !$plug->subscribtionListIsUptodate() ) + { + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_PLUGNEDUPDATE', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_PLUGNEDUPDATE']) ) + { + $subTpl = "

<%updatealert%>"; + } + else + { + $subTpl = $templates['SHOWLIST_LISTPLUG_TABLE_PLUGNEDUPDATE']; + } + $subData = array( + 'updatealert' => _LIST_PLUG_SUBS_NEEDUPDATE, + ); + $data['needupdate'] = Template::fill($subTpl, $subData); + } + else + { + $data['needupdate'] = ''; + } + if ( count($plug->getPluginDep() ) > 0) + { + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_PLUGIN_DEPEND', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_PLUGIN_DEPEND']) ) + { + $subTpl = "

<%deplistlbl%>
<%dependlist%>"; + } + else + { + $subTpl = $templates['SHOWLIST_LISTPLUG_TABLE_PLUGIN_DEPEND']; + } + $subData = array( + 'deplistlbl' => _LIST_PLUGS_DEP, + 'dependlist' => Entity::hsc(implode(', ', $plug->getPluginDep())), + ); + $data['dependlist'] = Template::fill($subTpl, $subData); + } + else + { + $data['dependlist'] = ''; + } + /* check dependency */ + if ( empty($plugins) ) + { + $plugins = DB::getResult('SELECT pfile FROM ' . sql_table('plugin')); + } + $req = array(); + foreach ( $plugins as $plugin ) + { + $preq =& $manager->getPlugin($plugin['pfile']); ++>>>>>>> skinnable-master if ( $preq ) { $depList = $preq->getPluginDep(); @@@ -279,7 -520,7 +779,11 @@@ { if ( $current['pfile'] == $depName ) { ++<<<<<<< HEAD + $req[] = $row['pfile']; ++======= + $req[] = $plugin['pfile']; ++>>>>>>> skinnable-master } } } @@@ -287,681 -528,1937 +791,2596 @@@ if ( count($req) > 0 ) { ++<<<<<<< HEAD + echo '
' . _LIST_PLUGS_DEPREQ . "
\n"; + echo '
' . Entity::hsc(implode(', ', $req)) . "
\n"; + } + + /* check the database to see if it is up-to-date and notice the user if not */ + if ( !$plug->subscribtionListIsUptodate() ) + { + echo '
' . 'NOTICE:' . "
\n"; + echo '
' . _LIST_PLUG_SUBS_NEEDUPDATE . "
\n"; + } + + echo "
\n"; + echo "\n"; + } + else + { + echo '' . sprintf(_PLUGINFILE_COULDNT_BELOADED, Entity::hsc($current['pfile'])) . "\n"; + } + + echo "\n"; + echo "
    \n"; + $current['pid'] = (integer) $current['pid']; + + $url = Entity::hsc($manager->addTicketToUrl("index.php?plugid={$current['pid']}&action=pluginup")); + echo "
  • " , _LIST_PLUGS_UP , "
  • \n"; + + $url = Entity::hsc($manager->addTicketToUrl("index.php?plugid={$current['pid']}&action=plugindown")); + echo "
  • " . _LIST_PLUGS_DOWN , "
  • \n"; + echo "
  • " . _LIST_PLUGS_UNINSTALL , "
  • \n"; + + if ( $plug && ($plug->hasAdminArea() > 0) ) + { + echo '
  • ' , _LIST_PLUGS_ADMIN , "
  • \n"; + } + + if ( $plug && ($plug->supportsFeature('HelpPage') > 0) ) + { + echo "
  • " . _LIST_PLUGS_HELP , "
  • \n"; + } + + $query = "SELECT COUNT(*) AS result FROM %s WHERE ocontext='global' and opid=%s;"; + $query = sprintf($query, sql_table('plugin_option_desc'), (integer) $current['pid']); + if ( DB::getValue($query) > 0 ) + { + echo "
  • " . _LIST_PLUGS_OPTIONS . "
  • \n"; + } + echo "
\n"; + echo "\n"; + break; + } + return; +} + +function listplug_table_plugoptionlist($template, $type) +{ + global $manager; + switch( $type ) + { + case 'HEAD': + echo '' . _LISTS_INFO . "\n"; + echo '' . _LISTS_VALUE . "\n"; + break; + case 'BODY': + listplug_plugOptionRow($template['current']); + break; + case 'FOOT': + echo "\n"; + echo '' . _PLUGS_SAVE . "\n"; + echo "\n"; + echo "\n"; + echo "" . _PLUGS_SAVE . "\n"; + echo "\n"; + echo "\n"; + break; + } + return; +} + +function listplug_plugOptionRow($current) +{ - $varname = "plugoption[{$current['oid']}][{$current['contextid']}]"; - - // retreive the optionmeta - $meta = NucleusPlugin::getOptionMeta($current['typeinfo']); - - // only if it is not a hidden option write the controls to the page - if ( in_array('access', $meta) && $meta['access'] == 'hidden' ) - { - return; - } - - if ( !$current['description'] ) - { - echo '' , Entity::hsc($current['name']) . "\n"; - } - else - { - if ( !defined($current['description']) ) - { - echo '' , Entity::hsc($current['description']) . "\n"; - } - else - { - echo '' , Entity::hsc(constant($current['description'])) . "\n"; - } - } - echo "\n"; - switch($current['type']) - { - case 'yesno': - Admin::input_yesno($varname, $current['value'], 0, 'yes', 'no'); - break; - case 'password': - echo '\n"; - break; - case 'select': - echo '\" />\n" + . "\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_POPTLIST_FOOT']; + } + $data = array( + 'savetext' => _PLUGS_SAVE, + ); + break; + } + + return Template::fill($template, $data); + } + + function listplug_plugOptionRow($current, $template_name = '') + { + global $manager; + + $templates = array(); + if ( !empty($template_name) ) + { + $templates =& $manager->getTemplate($template_name); + } + ++>>>>>>> skinnable-master + $varname = "plugoption[{$current['oid']}][{$current['contextid']}]"; + + // retreive the optionmeta + $meta = NucleusPlugin::getOptionMeta($current['typeinfo']); + + // only if it is not a hidden option write the controls to the page + if ( in_array('access', $meta) && $meta['access'] == 'hidden' ) + { ++<<<<<<< HEAD ++ return; ++ } ++ ++ if ( !$current['description'] ) ++ { ++ echo '' , Entity::hsc($current['name']) . "\n"; ++ } ++ else ++ { ++ if ( !defined($current['description']) ) ++ { ++ echo '' , Entity::hsc($current['description']) . "\n"; ++ } ++ else ++ { ++ echo '' , Entity::hsc(constant($current['description'])) . "\n"; ++ } ++ } ++ echo "\n"; ++ switch($current['type']) ++ { ++ case 'yesno': ++ Admin::input_yesno($varname, $current['value'], 0, 'yes', 'no'); ++ break; ++ case 'password': ++ echo '\n"; ++ break; ++ case 'select': ++ echo '\n"; + + break; + case 'textarea': + //$meta = NucleusPlugin::getOptionMeta($current['typeinfo']); + if ( array_key_exists('access', $meta) && $meta['access'] == 'readonly' ) + { + echo '\n"; + break; + case 'text': + default: + //$meta = NucleusPlugin::getOptionMeta($current['typeinfo']); + echo '\n"; + } + if ( array_key_exists('extra', $current) ) + { + echo $current['extra']; + } + echo "\n"; + + return; +} + +function listplug_table_itemlist($template, $type) +{ + $cssclass = ''; - - switch( $type ) - { - case 'HEAD': - echo ""._LIST_ITEM_INFO."\n"; - echo ""._LIST_ITEM_CONTENT."\n"; - echo ""._LISTS_ACTIONS.""; - break; - case 'BODY': - $current = $template['current']; - // string -> unix timestamp - $current['itime'] = strtotime($current['itime']); - - if ( $current['idraft'] == 1 ) - { - $cssclass = " class='draft'"; - } - - // (can't use offset time since offsets might vary between blogs) - if ( $current['itime'] > $template['now'] ) - { - $cssclass = " class='future'"; - } - - echo "\n"; - echo "
\n"; - echo '
' . _LIST_ITEM_BLOG . "
\n"; - echo '
' . Entity::hsc($current['bshortname']) . "
\n"; - echo '
' . _LIST_ITEM_CAT . "
\n"; - echo '
' . Entity::hsc($current['cname']) . "
\n"; - echo '
' . _LIST_ITEM_AUTHOR . "
\n"; - echo '
' . Entity::hsc($current['mname']) . "
\n"; - echo '
' . _LIST_ITEM_DATE . "
\n"; - echo '
' . date("Y-m-d",$current['itime']) . "
\n"; - echo '
' . _LIST_ITEM_TIME . "
\n"; - echo '
' . date("H:i",$current['itime']) . "
\n"; - echo "
\n"; - echo "\n"; - - $id = listplug_nextBatchId(); - - echo "\n"; - echo "

\n"; - echo "\n"; - echo "\n"; - echo "

\n"; - - $current['ibody'] = strip_tags($current['ibody']); - $current['ibody'] = Entity::hsc(Entity::shorten($current['ibody'], 300, '...')); - echo "

{$current['ibody']}

\n"; - echo "\n"; - - echo "\n"; - echo "\n"; - echo "\n"; - break; ++======= + return false; } - return; - } - - // for batch operations: generates the index numbers for checkboxes - function listplug_nextBatchId() - { - static $id = 0; - return $id++; - } - - function listplug_table_commentlist($template, $type) - { - switch( $type ) + else { - case 'HEAD': - echo '' . _LISTS_INFO . "\n"; - echo '' . _LIST_COMMENT . "\n"; - echo '' . _LISTS_ACTIONS . ""; - break; - case 'BODY': - $current = $template['current']; - $current['ctime'] = strtotime($current['ctime']); // string -> unix timestamp - - echo "\n"; - echo "
    \n"; - echo '
  • ' . date("Y-m-d@H:i",$current['ctime']) . "
  • \n"; - if ( isset($current['mname']) ) - { - echo '
  • ' . Entity::hsc($current['mname']) ,' ', _LIST_COMMENTS_MEMBER . "
  • \n"; - } - else - { - echo '
  • ' . Entity::hsc($current['cuser']) . "
  • \n"; - } - if ( isset($current['cmail']) && $current['cmail'] ) - { - echo '
  • ' . Entity::hsc($current['cmail']) . "
  • \n"; - } - if ( isset($current['cemail']) && $current['cemail'] ) - { - echo '
  • ' . Entity::hsc($current['cemail']) . "
  • \n"; + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_POPTLIST_BODY', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_POPTLIST_BODY']) ) + { + $template = "<%description%>\n" + . "\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_POPTLIST_BODY']; + } + + $data = array(); + + switch($current['type']) + { + case 'yesno': + $template .= listplug_input_yesno($varname, $current['value'], 0, 'yes', 'no', _YES, _NO, 0, $template_name, 1); + break; + case 'password': + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_PLGOPT_OPWORD', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_PLGOPT_OPWORD']) ) + { + $template .= "\" value=\"<%value%>\" />\n"; + } + else + { + $template .= $templates['SHOWLIST_LISTPLUG_TABLE_PLGOPT_OPWORD']; + } + $data = array( + 'varname' => Entity::hsc($varname), + 'value' => Entity::hsc($current['value']), + ); + break; + case 'select': + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_PLGOPT_OSELEP', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_PLGOPT_OSELEP']) ) + { + $template .= "\n"; + } + else + { + $template .= $templates['SHOWLIST_LISTPLUG_TABLE_PLGOPT_OSELEC']; + } + $data['varname'] = Entity::hsc($varname); + break; + case 'textarea': + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_PLGOPT_OTAREA', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_PLGOPT_OTAREA']) ) + { + $template .= "\n"; + } + else + { + $template .= $templates['SHOWLIST_LISTPLUG_TABLE_PLGOPT_OTAREA']; + } + $data = array( + 'varname' => Entity::hsc($varname), + 'value' => Entity::hsc($current['value']) + ); + if ( !array_key_exists('access', $current) || $current['access'] != 'readonly') + { + $data['readonly'] = ''; + } + else + { + $data['readonly'] = ' readonly="readonly"'; + } + break; + case 'text': + default: + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_PLGOPT_OITEXT', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_PLGOPT_OITEXT']) ) + { + $template .= "\" value=\"<%value%>\"<%datatype%><%readonly%> />\n"; + } + else + { + $template .= $templates['SHOWLIST_LISTPLUG_TABLE_PLGOPT_OITEXT']; + } + $data = array( + 'varname' => Entity::hsc($varname), + 'value' => Entity::hsc($current['value']) + ); + if ( !array_key_exists('datatype', $current) || $current['datatype'] != 'numerical') + { + $data['datatype'] = ''; + } + else + { + $data['datatype'] = ' onkeyup="checkNumeric(this)" onblur="checkNumeric(this)"'; + } + if ( !array_key_exists('access', $current) || $current['access'] != 'readonly') + { + $data['readonly'] = ''; + } + else + { + $data['readonly'] = ' readonly="readonly"'; + } + } + + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_PLUGOPTN_FOOT', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_PLUGOPTN_FOOT']) ) + { + $template .= "<%extra%>\n"; + } + else + { + $template .= $templates['SHOWLIST_LISTPLUG_TABLE_PLUGOPTN_FOOT']; + } + + if ( !array_key_exists('extra', $current) ) + { + $data['extra'] = ''; + } + else + { + $data['extra'] = Entity::hsc($current['extra']); + } + + if ( !array_key_exists('description', $current) ) + { + $data['description'] = Entity::hsc($current['name']); + } + else if ( !defined($current['description']) ) + { + $data['description'] = Entity::hsc($current['description']); + } + else + { + $data['description'] = Entity::hsc(constant($current['description'])); + } + } + return Template::fill($template, $data, 1); + } + + /** + * listplug_templateEditRow() + * + * @param array $content content of target template + * @param string $desc description of target template + * @param string $name name of target template + * @param string $help help text + * @param integer $tabindex a number for tab index + * @param boolean $big large or small textarea + * @param array $template_name name of template for filling + * @return void + */ + function listplug_templateEditRow($content, $desc, $name, $help = '', $tabindex = 0, $big = 0, $template_name = '') + { + global $manager; + + static $count = 0; + + $tmplt = array(); + $base = array(); + + $templates = array(); + if ( $template_name ) + { + $templates =& $manager->getTemplate($template_name); + } + + $data = array( + 'description' => $desc, + 'help' => empty($help) ? '' : helpHtml('template' . $help), + 'count' => $count++, + 'name' => $name, + 'tabindex' => $tabindex, + 'rows' => $big ? 10 : 5, + ); + + $message = ''; + + /* row head */ + if ( !array_key_exists('TEMPLATE_EDIT_ROW_HEAD', $templates) || empty($tmplt['TEMPLATE_EDIT_ROW_HEAD']) ) + { + $template = "\n" + . "<%description%><%help%>\n" + . "\">\n" + . "\n" + . "\n" + . "\n"; + } + else + { + $template = $tmplt['TEMPLATE_EDIT_ROW_TAIL']; + } + $message .= TEMPLATE::fill($template, $data); + + return $message; + } + + function listplug_table_itemlist($vars, $type, $template_name = '') + { + global $manager; + + $cssclass = ''; + + $templates = array(); + if ( !empty($template_name) ) + { + $templates =& $manager->getTemplate($template_name); + } ++>>>>>>> skinnable-master + + switch( $type ) + { + case 'HEAD': ++<<<<<<< HEAD ++ echo ""._LIST_ITEM_INFO."\n"; ++ echo ""._LIST_ITEM_CONTENT."\n"; ++ echo ""._LISTS_ACTIONS.""; ++ break; ++ case 'BODY': ++ $current = $template['current']; ++ // string -> unix timestamp ++ $current['itime'] = strtotime($current['itime']); ++ ++ if ( $current['idraft'] == 1 ) ++ { ++ $cssclass = " class='draft'"; ++ } ++ ++ // (can't use offset time since offsets might vary between blogs) ++ if ( $current['itime'] > $template['now'] ) ++ { ++ $cssclass = " class='future'"; ++ } ++ ++ echo "\n"; ++ echo "
    \n"; ++ echo '
    ' . _LIST_ITEM_BLOG . "
    \n"; ++ echo '
    ' . Entity::hsc($current['bshortname']) . "
    \n"; ++ echo '
    ' . _LIST_ITEM_CAT . "
    \n"; ++ echo '
    ' . Entity::hsc($current['cname']) . "
    \n"; ++ echo '
    ' . _LIST_ITEM_AUTHOR . "
    \n"; ++ echo '
    ' . Entity::hsc($current['mname']) . "
    \n"; ++ echo '
    ' . _LIST_ITEM_DATE . "
    \n"; ++ echo '
    ' . date("Y-m-d",$current['itime']) . "
    \n"; ++ echo '
    ' . _LIST_ITEM_TIME . "
    \n"; ++ echo '
    ' . date("H:i",$current['itime']) . "
    \n"; ++ echo "
    \n"; ++ echo "\n"; ++ ++ $id = listplug_nextBatchId(); ++ ++ echo "\n"; ++ echo "

    \n"; ++ echo "\n"; ++ echo "\n"; ++ echo "

    \n"; ++ ++ $current['ibody'] = strip_tags($current['ibody']); ++ $current['ibody'] = Entity::hsc(Entity::shorten($current['ibody'], 300, '...')); ++ echo "

    {$current['ibody']}

    \n"; ++ echo "\n"; ++ ++ echo "\n"; ++ echo "\n"; + echo "\n"; ++ break; ++ } ++ return; ++======= + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_ITEMLIST_HEAD', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_ITEMLIST_HEAD']) ) + { + $template = "<%colinfo%>\n" + . "<%colcontent%>\n" + . "<%colaction%>\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_ITEMLIST_HEAD']; + } + $data = array( + 'colinfo' => _LIST_ITEM_INFO, + 'colcontent' => _LIST_ITEM_CONTENT, + 'colaction' => _LISTS_ACTIONS + ); + break; + case 'BODY': + $current = $vars['current']; + // string -> unix timestamp + $current['itime'] = strtotime($current['itime']); + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_ITEMLIST_BODY', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_ITEMLIST_BODY']) ) + { + $template = ">\n" + . "<%bshortlabel%> <%bshortnameval%>
    \n" + . "<%categorylabel%> <%categorynameval%>
    \n" + . "<%authorlabel%> <%authornameval%>
    \n" + . "<%itemdatelabel%> <%itemdateval%>
    \n" + . "<%itemtimelabel%> <%itemtimeval%>\n" + . "\n" + . ">\n" + . "\" name=\"batch[<%batchid%>]\" value=\"<%itemid%>\" />\n" + . "
    \n" + . "<%itembody%>\n" + . "\n" + . ">\n" + . "\"><%editbtn%>
    \n" + . "\"><%movebtn%>
    \n" + . "\"><%delbtn%>
    \n" + . "<%camount%>\n" + . "\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_ITEMLIST_BODY']; + } + $cssclass = ''; + + if ( $current['idraft'] == 1 ) + { + $cssclass = ' class="draft"'; + } + + // (can't use offset time since offsets might vary between blogs) + if ( $current['itime'] > $vars['now'] ) + { + $cssclass = ' class="future"'; + } + $body = strip_tags($current['ibody']); + $data = array( + 'cssclass' => $cssclass, + 'bshortlabel' => _LIST_ITEM_BLOG, + 'bshortnameval' => Entity::hsc($current['bshortname']), + 'categorylabel' => _LIST_ITEM_CAT, + 'categorynameval' => Entity::hsc($current['cname']), + 'authorlabel' => _LIST_ITEM_AUTHOR, + 'authornameval' => Entity::hsc($current['mname']), + 'itemdatelabel' => _LIST_ITEM_DATE, + 'itemdateval' => date("Y-m-d",$current['itime']), + 'itemdatelabel' => _LIST_ITEM_TIME, + 'itemdateval' => date("H:i",$current['itime']), + 'batchid' => listplug_nextBatchId(), + 'itemid' => $current['inumber'], + 'itemtitle' => Entity::hsc(strip_tags($current['ititle'])), + 'itembody' => Entity::hsc(Entity::shorten($body, 300, '...')), + 'editbtn' => _LISTS_EDIT, + 'movebtn' => _LISTS_MOVE, + 'delbtn' => _LISTS_DELETE, + ); + // evaluate amount of comments for the item + $comment = new Comments($current['inumber']); + $camount = $comment->amountComments(); + if ( $camount > 0 ) + { + $data['camount'] = "(" . sprintf(_LIST_ITEM_COMMENTS, $comment->amountComments()) . ")
    \n"; + } + else + { + $data['camount'] = _LIST_ITEM_NOCONTENT . "
    \n"; + } + break; + case 'FOOT': + if ( !array_key_exists('SHOWLIST_LISTPLUG_TABLE_ITEMLIST_FOOT', $templates) || empty($templates['SHOWLIST_LISTPLUG_TABLE_ITEMLIST_FOOT']) ) + { + $template = "\n"; + } + else + { + $template = $templates['SHOWLIST_LISTPLUG_TABLE_ITEMLIST_FOOT']; + } + $data = array(); + break; + } + return Template::fill($template, $data); ++>>>>>>> skinnable-master + } - $id = listplug_nextBatchId(); + // for batch operations: generates the index numbers for checkboxes + function listplug_nextBatchId() + { + static $id = 0; + return $id++; + } + ++<<<<<<< HEAD ++function listplug_table_commentlist($template, $type) ++{ ++ switch( $type ) ++ { ++ case 'HEAD': ++ echo '' . _LISTS_INFO . "\n"; ++ echo '' . _LIST_COMMENT . "\n"; ++ echo '' . _LISTS_ACTIONS . ""; ++ break; ++ case 'BODY': ++ $current = $template['current']; ++ $current['ctime'] = strtotime($current['ctime']); // string -> unix timestamp + - echo ''; - echo "\n"; - echo "