function qa_user_favorite_set($userid, $handle, $cookieid, $entitytype, $entityid, $favorite) { require_once QA_INCLUDE_DIR . 'qa-db-favorites.php'; require_once QA_INCLUDE_DIR . 'qa-app-limits.php'; require_once QA_INCLUDE_DIR . 'qa-app-updates.php'; if ($favorite) { qa_db_favorite_create($userid, $entitytype, $entityid); } else { qa_db_favorite_delete($userid, $entitytype, $entityid); } switch ($entitytype) { case QA_ENTITY_QUESTION: $action = $favorite ? 'q_favorite' : 'q_unfavorite'; $params = array('postid' => $entityid); break; case QA_ENTITY_USER: $action = $favorite ? 'u_favorite' : 'u_unfavorite'; $params = array('userid' => $entityid); break; case QA_ENTITY_TAG: $action = $favorite ? 'tag_favorite' : 'tag_unfavorite'; $params = array('wordid' => $entityid); break; case QA_ENTITY_CATEGORY: $action = $favorite ? 'cat_favorite' : 'cat_unfavorite'; $params = array('categoryid' => $entityid); break; default: qa_fatal_error('Favorite type not recognized'); break; } qa_report_event($action, $userid, $handle, $cookieid, $params); }
function process_request($request) { require_once QA_INCLUDE_DIR . 'qa-db-users.php'; require_once QA_INCLUDE_DIR . 'qa-app-format.php'; require_once QA_INCLUDE_DIR . 'qa-app-users.php'; require_once QA_INCLUDE_DIR . 'qa-db-selects.php'; require_once $this->directory . 'qa-open-utils.php'; // Check we're not using single-sign on integration, that we're logged in if (QA_FINAL_EXTERNAL_USERS) { qa_fatal_error('User accounts are handled by external code'); } $userid = qa_get_logged_in_userid(); if (!isset($userid)) { qa_redirect('login'); } // Get current information on user $useraccount = qa_db_user_find_by_id__open($userid); // Check if settings were updated $this->check_settings(); // Check if we're unlinking an account $mylogins = $this->check_unlink($useraccount); // Check if we need to associate another provider $tolink = $this->check_associate($useraccount); // Check if we're merging multiple accounts $otherlogins = $this->check_merge($useraccount, $mylogins, $tolink); // Prepare content for theme $disp_conf = qa_get('confirm') || !empty($tolink); $qa_content = qa_content_prepare(); // Build page if (!$disp_conf) { // just visiting the regular page $qa_content['title'] = qa_lang_html('plugin_open/my_logins_title'); $qa_content['navigation']['sub'] = qa_user_sub_navigation($useraccount['handle'], '', true); $qa_content['script_onloads'][] = '$(function(){ window.setTimeout(function() { qa_conceal(".form-notification-ok"); }, 1500); });'; $this->display_summary($qa_content, $useraccount); $this->display_logins($qa_content, $useraccount, $mylogins); $this->display_duplicates($qa_content, $useraccount, $otherlogins); $this->display_services($qa_content, !empty($mylogins) || !empty($otherlogins)); } else { // logged in and there are duplicates $qa_content['title'] = qa_lang_html('plugin_open/other_logins_conf_title'); if (!$this->display_duplicates($qa_content, $useraccount, $otherlogins)) { $tourl = qa_get('to'); if (!empty($tourl)) { qa_redirect($tourl); } else { if ($tolink) { // unable to link the login $provider = ucfirst($tolink['source']); qa_redirect('logins', array('provider' => $provider, 'code' => 99)); } else { // no merge to confirm qa_redirect('', array('provider' => '', 'code' => 98)); } } } } return $qa_content; }
function qa_db_count_active_users($table) { switch ($table) { case 'posts': case 'uservotes': case 'userpoints': break; default: qa_fatal_error('qa_db_count_active_users() called for unknown table'); break; } return qa_db_read_one_value(qa_db_query_sub('SELECT COUNT(DISTINCT(userid)) FROM ^' . $table)); }
function qa_complete_reset_user($userid) { require_once QA_INCLUDE_DIR . 'qa-util-string.php'; require_once QA_INCLUDE_DIR . 'qa-app-options.php'; require_once QA_INCLUDE_DIR . 'qa-app-emails.php'; require_once QA_INCLUDE_DIR . 'qa-app-cookies.php'; require_once QA_INCLUDE_DIR . 'qa-db-selects.php'; $password = qa_random_alphanum(max(QA_MIN_PASSWORD_LEN, QA_NEW_PASSWORD_LEN)); $userinfo = qa_db_select_with_pending(qa_db_user_account_selectspec($userid, true)); if (!qw_send_notification($userid, $userinfo['email'], $userinfo['handle'], qa_lang('emails/new_password_subject'), nl2br(qa_lang('emails/new_password_body')), array('^password' => $password, '^url' => qa_opt('site_url')))) { qa_fatal_error('Could not send new password - password not reset'); } qa_db_user_set_password($userid, $password); // do this last, to be safe qa_db_user_set($userid, 'emailcode', ''); // so can't be reused qa_report_event('u_reset', $userid, $userinfo['handle'], qa_cookie_get(), array('email' => $userinfo['email'])); }
function sendNewConfirm($userid) { require_once QA_INCLUDE_DIR . 'db/users.php'; require_once QA_INCLUDE_DIR . 'db/selects.php'; require_once QA_INCLUDE_DIR . 'app/emails.php'; $userinfo = qa_db_select_with_pending(qa_db_user_account_selectspec($userid, true)); if (!qa_send_notification($userid, $userinfo['email'], $userinfo['handle'], qa_lang('emails/confirm_subject'), qa_lang('emails/confirm_body'), array('^url' => getNewConfirmUrl($userid, $userinfo['handle'])))) { qa_fatal_error('Could not send email confirmation'); } // $userinfo=qa_db_select_with_pending(qa_db_user_account_selectspec($userid, true)); // $params = array(); // $params['fromemail'] = qa_opt('from_email'), // $params['fromname'] = qa_opt('site_title'), // $params['toemail'] = $userinfo['email']; // $params['toname'] = $userinfo['handle']; // $params['subject'] = qa_lang('emails/confirm_subject'); // $params['body'] = qa_lang('emails/confirm_body'); // qa_send_email($params); }
function process_request($request) { $start = qa_get_start(); $userid = qa_get_logged_in_userid(); // Prepare content for theme require_once QA_INCLUDE_DIR . 'qa-db-users.php'; require_once QA_INCLUDE_DIR . 'qa-app-format.php'; require_once QA_INCLUDE_DIR . 'qa-app-users.php'; require_once QA_INCLUDE_DIR . 'qa-db-selects.php'; require_once QW_CONTROL_DIR . '/addons/social-login/cs-social-login-utils.php'; if (QA_FINAL_EXTERNAL_USERS) { qa_fatal_error('User accounts are handled by external code'); } if (!isset($userid)) { qa_redirect('login'); } $qa_content = qa_content_prepare(); $qa_content['title'] = qa_lang_html('notification/my_notification_settings'); $qa_content['site_title'] = qa_opt('site_title'); if (qa_clicked('save_notf_user_settings')) { $data_to_save = array('qw_mail_when_a_post' => !!qa_post_text('qw_mail_when_a_post'), 'qw_mail_when_related' => !!qa_post_text('qw_mail_when_related'), 'qw_mail_when_c_post' => !!qa_post_text('qw_mail_when_c_post'), 'qw_mail_when_q_reshow' => !!qa_post_text('qw_mail_when_q_reshow'), 'qw_mail_when_c_reshow' => !!qa_post_text('qw_mail_when_c_reshow'), 'qw_mail_when_a_select' => !!qa_post_text('qw_mail_when_a_select'), 'qw_mail_when_q_vote_up' => !!qa_post_text('qw_mail_when_q_vote_up'), 'qw_mail_when_q_vote_down' => !!qa_post_text('qw_mail_when_q_vote_down'), 'qw_mail_when_a_vote_up' => !!qa_post_text('qw_mail_when_a_vote_up'), 'qw_mail_when_a_vote_down' => !!qa_post_text('qw_mail_when_a_vote_down'), 'qw_mail_when_q_favorite' => !!qa_post_text('qw_mail_when_q_favorite'), 'qw_mail_when_u_favorite' => !!qa_post_text('qw_mail_when_u_favorite'), 'qw_mail_when_u_message' => !!qa_post_text('qw_mail_when_u_message'), 'qw_mail_when_u_wall_post' => !!qa_post_text('qw_mail_when_u_wall_post'), 'qw_mail_when_u_level' => !!qa_post_text('qw_mail_when_u_level'), 'qw_mail_when_q_post_user_fl' => !!qa_post_text('qw_mail_when_q_post_user_fl'), 'qw_mail_when_q_post_tag_fl' => !!qa_post_text('qw_mail_when_q_post_tag_fl'), 'qw_mail_when_q_post_cat_fl' => !!qa_post_text('qw_mail_when_q_post_cat_fl'), 'qw_mail_when_q_approve' => !!qa_post_text('qw_mail_when_q_approve'), 'qw_mail_when_q_reject' => !!qa_post_text('qw_mail_when_q_reject'), 'qw_mail_when_a_approve' => !!qa_post_text('qw_mail_when_a_approve'), 'qw_mail_when_a_reject' => !!qa_post_text('qw_mail_when_a_reject'), 'qw_mail_when_c_approve' => !!qa_post_text('qw_mail_when_c_approve'), 'qw_mail_when_c_reject' => !!qa_post_text('qw_mail_when_c_reject')); qw_save_notification_settings(json_encode($data_to_save), $userid); qa_redirect('notification-settings', array('state' => 'settings-saved')); } $disp_conf = qa_get('confirm'); $preferences = qw_get_notification_settings($userid); // qw_log(print_r(qw_check_pref_for_event($userid , 'a_post') , true )) ; if (!$disp_conf) { // display some summary about the user $qa_content['form_profile'] = array('title' => qa_lang_html('notification/my_notification_settings'), 'tags' => 'METHOD="POST" ACTION="' . qa_self_html() . '" CLASS="social-login-settings"', 'style' => 'wide', 'buttons' => array('check_all' => array('type' => 'button', 'tags' => 'name="check_all_notf_fields" id="check_all_notf_fields" ', 'label' => qa_lang_html('notification/check_all')), 'uncheck_all' => array('type' => 'button', 'tags' => 'name="un_check_all_notf_fields" id="un_check_all_notf_fields" ', 'label' => qa_lang_html('notification/uncheck_all')), 'save' => array('tags' => 'onClick="qa_show_waiting_after(this, false);"', 'label' => qa_lang_html('notification/save_settings'))), 'fields' => array('qw_mail_when_a_post' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_a_post_lable'), 'tags' => 'NAME="qw_mail_when_a_post"', 'value' => @$preferences['qw_mail_when_a_post'] ? true : false), 'qw_mail_when_related' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_related_lable'), 'tags' => 'NAME="qw_mail_when_related"', 'value' => @$preferences['qw_mail_when_related'] ? true : false), 'qw_mail_when_c_post' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_c_post_lable'), 'tags' => 'NAME="qw_mail_when_c_post"', 'value' => @$preferences['qw_mail_when_c_post'] ? true : false), 'qw_mail_when_q_reshow' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_q_reshow_lable'), 'tags' => 'NAME="qw_mail_when_q_reshow"', 'value' => @$preferences['qw_mail_when_q_reshow'] ? true : false), 'qw_mail_when_c_reshow' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_c_reshow_lable'), 'tags' => 'NAME="qw_mail_when_c_reshow"', 'value' => @$preferences['qw_mail_when_c_reshow'] ? true : false), 'qw_mail_when_a_select' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_a_select_lable'), 'tags' => 'NAME="qw_mail_when_a_select"', 'value' => @$preferences['qw_mail_when_a_select'] ? true : false), 'qw_mail_when_q_vote_up' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_q_vote_up_lable'), 'tags' => 'NAME="qw_mail_when_q_vote_up"', 'value' => @$preferences['qw_mail_when_q_vote_up'] ? true : false), 'qw_mail_when_q_vote_down' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_q_vote_down_lable'), 'tags' => 'NAME="qw_mail_when_q_vote_down"', 'value' => @$preferences['qw_mail_when_q_vote_down'] ? true : false), 'qw_mail_when_a_vote_up' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_a_vote_up_lable'), 'tags' => 'NAME="qw_mail_when_a_vote_up"', 'value' => @$preferences['qw_mail_when_a_vote_up'] ? true : false), 'qw_mail_when_a_vote_down' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_a_vote_down_lable'), 'tags' => 'NAME="qw_mail_when_a_vote_down"', 'value' => @$preferences['qw_mail_when_a_vote_down'] ? true : false), 'qw_mail_when_q_favorite' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_q_favorite_lable'), 'tags' => 'NAME="qw_mail_when_q_favorite"', 'value' => @$preferences['qw_mail_when_q_favorite'] ? true : false), 'qw_mail_when_u_favorite' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_u_favorite_lable'), 'tags' => 'NAME="qw_mail_when_u_favorite"', 'value' => @$preferences['qw_mail_when_u_favorite'] ? true : false), 'qw_mail_when_u_message' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_u_message_lable'), 'tags' => 'NAME="qw_mail_when_u_message"', 'value' => @$preferences['qw_mail_when_u_message'] ? true : false), 'qw_mail_when_u_wall_post' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_u_wall_post_lable'), 'tags' => 'NAME="qw_mail_when_u_wall_post"', 'value' => @$preferences['qw_mail_when_u_wall_post'] ? true : false), 'qw_mail_when_u_level' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_u_level_lable'), 'tags' => 'NAME="qw_mail_when_u_level"', 'value' => @$preferences['qw_mail_when_u_level'] ? true : false), 'qw_mail_when_q_post_user_fl' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_q_post_user_fl_lable'), 'tags' => 'NAME="qw_mail_when_q_post_user_fl"', 'value' => @$preferences['qw_mail_when_q_post_user_fl'] ? true : false), 'qw_mail_when_q_post_tag_fl' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_q_post_tag_fl_lable'), 'tags' => 'NAME="qw_mail_when_q_post_tag_fl"', 'value' => @$preferences['qw_mail_when_q_post_tag_fl'] ? true : false), 'qw_mail_when_q_post_cat_fl' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_q_post_cat_fl_lable'), 'tags' => 'NAME="qw_mail_when_q_post_cat_fl"', 'value' => @$preferences['qw_mail_when_q_post_cat_fl'] ? true : false), 'qw_mail_when_q_approve' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_q_approve_lable'), 'tags' => 'NAME="qw_mail_when_q_approve"', 'value' => @$preferences['qw_mail_when_q_approve'] ? true : false), 'qw_mail_when_q_reject' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_q_reject_lable'), 'tags' => 'NAME="qw_mail_when_q_reject"', 'value' => @$preferences['qw_mail_when_q_reject'] ? true : false), 'qw_mail_when_a_approve' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_a_approve_lable'), 'tags' => 'NAME="qw_mail_when_a_approve"', 'value' => @$preferences['qw_mail_when_a_approve'] ? true : false), 'qw_mail_when_a_reject' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_a_reject_lable'), 'tags' => 'NAME="qw_mail_when_a_reject"', 'value' => @$preferences['qw_mail_when_a_reject'] ? true : false), 'qw_mail_when_c_approve' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_c_approve_lable'), 'tags' => 'NAME="qw_mail_when_c_approve"', 'value' => @$preferences['qw_mail_when_c_approve'] ? true : false), 'qw_mail_when_c_reject' => array('type' => 'checkbox', 'label' => qa_lang_html('notification/mail_when_c_reject_lable'), 'tags' => 'NAME="qw_mail_when_c_reject"', 'value' => @$preferences['qw_mail_when_c_reject'] ? true : false)), 'hidden' => array('save_notf_user_settings' => '1')); if (qa_get_state() == 'settings-saved') { $qa_content['form_profile']['ok'] = qa_lang_html('notification/settings_saved'); } } $qa_content['navigation']['sub'] = qa_account_sub_navigation(); return $qa_content; }
function less_css($handle) { include DUDE_THEME_DIR . "/less/variables.php"; // output css file name $css_path = DUDE_THEME_DIR . '/css/' . "{$handle}.css"; // automatically regenerate files if source's modified time has changed or vars have changed try { // initialise the parser $less = new lessc(); // load the cache $cache_path = DUDE_THEME_DIR . "/cache/{$handle}.css.cache"; if (file_exists($cache_path)) { $cache = unserialize(file_get_contents($cache_path)); } // If the cache or root path in it are invalid then regenerate if (empty($cache) || empty($cache['less']['root']) || !file_exists($cache['less']['root'])) { $cache = array('vars' => $vars, 'less' => DUDE_THEME_DIR . "/less/{$handle}.less"); } // less config $less->setFormatter("compressed"); $less->setVariables($vars); $less_cache = $less->cachedCompile($cache['less'], false); if (!file_exists($css_path) || empty($cache) || empty($cache['less']['updated']) || $less_cache['updated'] > $cache['less']['updated']) { file_put_contents($cache_path, serialize(array('vars' => $vars, 'less' => $less_cache))); file_put_contents($css_path, $less_cache['compiled']); } elseif ($vars !== $cache['vars']) { $less_cache = $less->cachedCompile($cache['less'], true); file_put_contents($cache_path, serialize(array('vars' => $vars, 'less' => $less_cache))); file_put_contents($css_path, $less_cache['compiled']); } } catch (exception $ex) { qa_fatal_error($ex->getMessage()); } // return the compiled stylesheet with the query string it had if any $url = DUDE_THEME_URL . "/css/{$handle}.css"; echo '<link href="' . $url . '" type="text/css" rel="stylesheet">'; }
function qa_register_plugin_layer($include, $name) { global $qa_plugin_directory, $qa_plugin_urltoroot; if (empty($qa_plugin_directory) || empty($qa_plugin_urltoroot)) { qa_fatal_error('qa_register_plugin_layer() can only be called from a plugin qa-plugin.php file'); } qa_register_layer($include, $name, $qa_plugin_directory, $qa_plugin_urltoroot); }
/** * Return the first column of the first row (and presumably only cell) from the $result resource. * If there's no first row, throw a fatal error unless $allowempty is true. */ function qa_db_read_one_value($result, $allowempty = false) { if (!$result instanceof mysqli_result) { qa_fatal_error('Reading one value from invalid result'); } $row = $result->fetch_row(); if (is_array($row)) { return $row[0]; } if ($allowempty) { return null; } else { qa_fatal_error('Reading one value from empty results'); } }
function qa_db_upgrade_tables() { require_once QA_INCLUDE_DIR . 'qa-app-recalc.php'; $definitions = qa_db_table_definitions(); $keyrecalc = array(); // Write-lock all QA tables before we start so no one can read or write anything $keydbtables = qa_array_to_lower_keys(qa_db_read_all_values(qa_db_query_raw('SHOW TABLES'))); foreach ($definitions as $rawname => $definition) { if (isset($keydbtables[strtolower(qa_db_add_table_prefix($rawname))])) { $locks[] = '^' . $rawname . ' WRITE'; } } $locktablesquery = 'LOCK TABLES ' . implode(', ', $locks); qa_db_upgrade_query($locktablesquery); // Upgrade it step-by-step until it's up to date (do LOCK TABLES after ALTER TABLE because the lock can sometimes be lost) while (1) { $version = qa_db_get_db_version(); if ($version >= QA_DB_VERSION_CURRENT) { break; } $newversion = $version + 1; qa_db_upgrade_progress(QA_DB_VERSION_CURRENT - $version . ' upgrade step/s remaining...'); switch ($newversion) { // Up to here: Version 1.0 beta 1 case 2: qa_db_upgrade_query('ALTER TABLE ^posts DROP COLUMN votes, ADD COLUMN (upvotes ' . $definitions['posts']['upvotes'] . ', downvotes ' . $definitions['posts']['downvotes'] . ')'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecountposts'] = true; break; case 3: qa_db_upgrade_query('ALTER TABLE ^userpoints ADD COLUMN (upvoteds ' . $definitions['userpoints']['upvoteds'] . ', downvoteds ' . $definitions['userpoints']['downvoteds'] . ')'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecalcpoints'] = true; break; case 4: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN lastuserid ' . $definitions['posts']['lastuserid'] . ', CHANGE COLUMN updated updated ' . $definitions['posts']['updated']); qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('UPDATE ^posts SET updated=NULL WHERE updated=0 OR updated=created'); break; case 5: qa_db_upgrade_query('ALTER TABLE ^contentwords ADD COLUMN (type ' . $definitions['contentwords']['type'] . ', questionid ' . $definitions['contentwords']['questionid'] . ')'); qa_db_upgrade_query($locktablesquery); $keyrecalc['doreindexposts'] = true; break; // Up to here: Version 1.0 beta 2 // Up to here: Version 1.0 beta 2 case 6: qa_db_upgrade_query('ALTER TABLE ^userpoints ADD COLUMN cposts ' . $definitions['userpoints']['cposts']); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecalcpoints'] = true; break; case 7: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN sessioncode ' . $definitions['users']['sessioncode']); qa_db_upgrade_query($locktablesquery); } break; case 8: qa_db_upgrade_query('ALTER TABLE ^posts ADD KEY (type, acount, created)'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecountposts'] = true; // for unanswered question count break; // Up to here: Version 1.0 beta 3, 1.0, 1.0.1 beta, 1.0.1 // Up to here: Version 1.0 beta 3, 1.0, 1.0.1 beta, 1.0.1 case 9: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query('ALTER TABLE ^users CHANGE COLUMN resetcode emailcode ' . $definitions['users']['emailcode'] . ', ADD COLUMN flags ' . $definitions['users']['flags']); qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('UPDATE ^users SET flags=1'); } break; case 10: qa_db_upgrade_query(qa_db_create_table_sql('categories', array('categoryid' => $definitions['categories']['categoryid'], 'title' => $definitions['categories']['title'], 'tags' => $definitions['categories']['tags'], 'qcount' => $definitions['categories']['qcount'], 'position' => $definitions['categories']['position'], 'PRIMARY KEY (categoryid)', 'UNIQUE tags (tags)', 'UNIQUE position (position)'))); // hard-code list of columns and indexes to ensure we ignore any added at a later stage $locktablesquery .= ', ^categories WRITE'; qa_db_upgrade_query($locktablesquery); break; case 11: qa_db_upgrade_query('ALTER TABLE ^posts ADD CONSTRAINT ^posts_ibfk_2 FOREIGN KEY (parentid) REFERENCES ^posts(postid), ADD COLUMN categoryid ' . $definitions['posts']['categoryid'] . ', ADD KEY categoryid (categoryid, type, created), ADD CONSTRAINT ^posts_ibfk_3 FOREIGN KEY (categoryid) REFERENCES ^categories(categoryid) ON DELETE SET NULL'); // foreign key on parentid important now that deletion is possible qa_db_upgrade_query($locktablesquery); break; case 12: qa_db_upgrade_query(qa_db_create_table_sql('pages', array('pageid' => $definitions['pages']['pageid'], 'title' => $definitions['pages']['title'], 'nav' => $definitions['pages']['nav'], 'position' => $definitions['pages']['position'], 'flags' => $definitions['pages']['flags'], 'tags' => $definitions['pages']['tags'], 'heading' => $definitions['pages']['heading'], 'content' => $definitions['pages']['content'], 'PRIMARY KEY (pageid)', 'UNIQUE tags (tags)', 'UNIQUE position (position)'))); // hard-code list of columns and indexes to ensure we ignore any added at a later stage $locktablesquery .= ', ^pages WRITE'; qa_db_upgrade_query($locktablesquery); break; case 13: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN createip ' . $definitions['posts']['createip'] . ', ADD KEY createip (createip, created)'); qa_db_upgrade_query($locktablesquery); break; case 14: qa_db_upgrade_query('ALTER TABLE ^userpoints DROP COLUMN qvotes, DROP COLUMN avotes, ADD COLUMN (qupvotes ' . $definitions['userpoints']['qupvotes'] . ', qdownvotes ' . $definitions['userpoints']['qdownvotes'] . ', aupvotes ' . $definitions['userpoints']['aupvotes'] . ', adownvotes ' . $definitions['userpoints']['adownvotes'] . ')'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecalcpoints'] = true; break; // Up to here: Version 1.2 beta 1 // Up to here: Version 1.2 beta 1 case 15: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_table_columns($definitions, 'users', array('emailcode', 'sessioncode', 'flags')); } qa_db_upgrade_table_columns($definitions, 'posts', array('acount', 'upvotes', 'downvotes', 'format')); qa_db_upgrade_table_columns($definitions, 'categories', array('qcount')); qa_db_upgrade_table_columns($definitions, 'words', array('titlecount', 'contentcount', 'tagcount')); qa_db_upgrade_table_columns($definitions, 'userpoints', array('points', 'qposts', 'aposts', 'cposts', 'aselects', 'aselecteds', 'qupvotes', 'qdownvotes', 'aupvotes', 'adownvotes', 'qvoteds', 'avoteds', 'upvoteds', 'downvoteds')); qa_db_upgrade_query($locktablesquery); break; // Up to here: Version 1.2 (release) // Up to here: Version 1.2 (release) case 16: qa_db_upgrade_table_columns($definitions, 'posts', array('format')); qa_db_upgrade_query($locktablesquery); $keyrecalc['doreindexposts'] = true; // because of new treatment of apostrophes in words break; case 17: qa_db_upgrade_query('ALTER TABLE ^posts ADD KEY updated (updated, type), ADD KEY categoryid_2 (categoryid, updated, type)'); qa_db_upgrade_query($locktablesquery); break; case 18: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN lastip ' . $definitions['posts']['lastip'] . ', ADD KEY lastip (lastip, updated, type)'); qa_db_upgrade_query($locktablesquery); break; case 19: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN avatarblobid ' . $definitions['users']['avatarblobid'] . ', ADD COLUMN avatarwidth ' . $definitions['users']['avatarwidth'] . ', ADD COLUMN avatarheight ' . $definitions['users']['avatarheight']); } // hard-code list of columns and indexes to ensure we ignore any added at a later stage qa_db_upgrade_query(qa_db_create_table_sql('blobs', array('blobid' => $definitions['blobs']['blobid'], 'format' => $definitions['blobs']['format'], 'content' => $definitions['blobs']['content'], 'PRIMARY KEY (blobid)'))); qa_db_upgrade_query(qa_db_create_table_sql('cache', array('type' => $definitions['cache']['type'], 'cacheid' => $definitions['cache']['cacheid'], 'content' => $definitions['cache']['content'], 'created' => $definitions['cache']['created'], 'lastread' => $definitions['cache']['lastread'], 'PRIMARY KEY (type,cacheid)', 'KEY (lastread)'))); // hard-code list of columns and indexes to ensure we ignore any added at a later stage $locktablesquery .= ', ^blobs WRITE, ^cache WRITE'; qa_db_upgrade_query($locktablesquery); break; case 20: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query(qa_db_create_table_sql('userlogins', array('userid' => $definitions['userlogins']['userid'], 'source' => $definitions['userlogins']['source'], 'identifier' => $definitions['userlogins']['identifier'], 'identifiermd5' => $definitions['userlogins']['identifiermd5'], 'KEY source (source, identifiermd5)', 'KEY userid (userid)', 'CONSTRAINT ^userlogins_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE'))); qa_db_upgrade_query('ALTER TABLE ^users CHANGE COLUMN passsalt passsalt ' . $definitions['users']['passsalt'] . ', CHANGE COLUMN passcheck passcheck ' . $definitions['users']['passcheck']); $locktablesquery .= ', ^userlogins WRITE'; qa_db_upgrade_query($locktablesquery); } break; case 21: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query(qa_db_create_table_sql('userfields', array('fieldid' => $definitions['userfields']['fieldid'], 'title' => $definitions['userfields']['title'], 'content' => $definitions['userfields']['content'], 'position' => $definitions['userfields']['position'], 'flags' => $definitions['userfields']['flags'], 'PRIMARY KEY (fieldid)'))); $locktablesquery .= ', ^userfields WRITE'; qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query(qa_db_default_userfields_sql()); } break; // Up to here: Version 1.3 beta 1 // Up to here: Version 1.3 beta 1 case 22: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN sessionsource ' . $definitions['users']['sessionsource']); qa_db_upgrade_query($locktablesquery); } break; // Up to here: Version 1.3 beta 2 and release // Up to here: Version 1.3 beta 2 and release case 23: qa_db_upgrade_query(qa_db_create_table_sql('widgets', array('widgetid' => $definitions['widgets']['widgetid'], 'place' => $definitions['widgets']['place'], 'position' => $definitions['widgets']['position'], 'tags' => $definitions['widgets']['tags'], 'title' => $definitions['widgets']['title'], 'PRIMARY KEY (widgetid)', 'UNIQUE position (position)'))); $locktablesquery .= ', ^widgets WRITE'; qa_db_upgrade_query($locktablesquery); break; case 24: qa_db_upgrade_query(qa_db_create_table_sql('tagwords', array('postid' => $definitions['tagwords']['postid'], 'wordid' => $definitions['tagwords']['wordid'], 'KEY postid (postid)', 'KEY wordid (wordid)', 'CONSTRAINT ^tagwords_ibfk_1 FOREIGN KEY (postid) REFERENCES ^posts(postid) ON DELETE CASCADE', 'CONSTRAINT ^tagwords_ibfk_2 FOREIGN KEY (wordid) REFERENCES ^words(wordid)'))); $locktablesquery .= ', ^tagwords WRITE'; qa_db_upgrade_query('ALTER TABLE ^words ADD COLUMN tagwordcount ' . $definitions['words']['tagwordcount']); qa_db_upgrade_query($locktablesquery); $keyrecalc['doreindexposts'] = true; break; // Up to here: Version 1.4 developer preview // Up to here: Version 1.4 developer preview case 25: $keycolumns = qa_array_to_lower_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^blobs'))); // might be using blobs table shared with another installation, so check if we need to upgrade if (isset($keycolumns['filename'])) { qa_db_upgrade_progress('Skipping upgrading blobs table since it was already upgraded by another QA site sharing it.'); } else { qa_db_upgrade_query('ALTER TABLE ^blobs ADD COLUMN filename ' . $definitions['blobs']['filename'] . ', ADD COLUMN userid ' . $definitions['blobs']['userid'] . ', ADD COLUMN cookieid ' . $definitions['blobs']['cookieid'] . ', ADD COLUMN createip ' . $definitions['blobs']['createip'] . ', ADD COLUMN created ' . $definitions['blobs']['created']); qa_db_upgrade_query($locktablesquery); } break; case 26: qa_db_upgrade_query('ALTER TABLE ^uservotes ADD COLUMN flag ' . $definitions['uservotes']['flag']); qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN flagcount ' . $definitions['posts']['flagcount'] . ', ADD KEY type_3 (type, flagcount, created)'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecountposts'] = true; break; case 27: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN netvotes ' . $definitions['posts']['netvotes'] . ', ADD KEY type_4 (type, netvotes, created)'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecountposts'] = true; break; case 28: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN views ' . $definitions['posts']['views'] . ', ADD COLUMN hotness ' . $definitions['posts']['hotness'] . ', ADD KEY type_5 (type, views, created), ADD KEY type_6 (type, hotness)'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecountposts'] = true; break; case 29: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN lastviewip ' . $definitions['posts']['lastviewip']); qa_db_upgrade_query($locktablesquery); break; case 30: qa_db_upgrade_query('ALTER TABLE ^posts DROP FOREIGN KEY ^posts_ibfk_3'); // to allow category column types to be changed qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('ALTER TABLE ^posts DROP KEY categoryid, DROP KEY categoryid_2'); qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('ALTER TABLE ^categories CHANGE COLUMN categoryid categoryid ' . $definitions['categories']['categoryid'] . ', ADD COLUMN parentid ' . $definitions['categories']['parentid'] . ', ADD COLUMN backpath ' . $definitions['categories']['backpath'] . ', ADD COLUMN content ' . $definitions['categories']['content'] . ', DROP INDEX tags, DROP INDEX position, ADD UNIQUE parentid (parentid, tags), ADD UNIQUE parentid_2 (parentid, position), ADD KEY backpath (backpath(' . QA_DB_MAX_CAT_PAGE_TAGS_LENGTH . '))'); qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('ALTER TABLE ^posts CHANGE COLUMN categoryid categoryid ' . $definitions['posts']['categoryid'] . ', ADD COLUMN catidpath1 ' . $definitions['posts']['catidpath1'] . ', ADD COLUMN catidpath2 ' . $definitions['posts']['catidpath2'] . ', ADD COLUMN catidpath3 ' . $definitions['posts']['catidpath3']); // QA_CATEGORY_DEPTH=4 qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('ALTER TABLE ^posts ADD KEY catidpath1 (catidpath1, type, created), ADD KEY catidpath2 (catidpath2, type, created), ADD KEY catidpath3 (catidpath3, type, created), ADD KEY categoryid (categoryid, type, created), ADD KEY catidpath1_2 (catidpath1, updated, type), ADD KEY catidpath2_2 (catidpath2, updated, type), ADD KEY catidpath3_2 (catidpath3, updated, type), ADD KEY categoryid_2 (categoryid, updated, type)'); qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('ALTER TABLE ^posts ADD CONSTRAINT ^posts_ibfk_3 FOREIGN KEY (categoryid) REFERENCES ^categories(categoryid) ON DELETE SET NULL'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecalccategories'] = true; break; // Up to here: Version 1.4 beta 1 and 2 } qa_db_set_db_version($newversion); if (qa_db_get_db_version() != $newversion) { qa_fatal_error('Could not increment database version'); } } qa_db_upgrade_query('UNLOCK TABLES'); // Perform any necessary recalculations, as determined by upgrade steps foreach ($keyrecalc as $state => $dummy) { while ($state) { set_time_limit(60); $stoptime = time() + 2; while (qa_recalc_perform_step($state) && time() < $stoptime) { } qa_db_upgrade_progress(qa_recalc_get_message($state)); } } }
function qa_log_in_external_user($source, $identifier, $fields) { if (qa_to_override(__FUNCTION__)) { $args = func_get_args(); return qa_call_override(__FUNCTION__, $args); } require_once QA_INCLUDE_DIR . 'db/users.php'; $users = qa_db_user_login_find($source, $identifier); $countusers = count($users); if ($countusers > 1) { qa_fatal_error('External login mapped to more than one user'); } // should never happen if ($countusers) { // user exists so log them in qa_set_logged_in_user($users[0]['userid'], $users[0]['handle'], false, $source); } else { // create and log in user require_once QA_INCLUDE_DIR . 'app/users-edit.php'; qa_db_user_login_sync(true); $users = qa_db_user_login_find($source, $identifier); // check again after table is locked if (count($users) == 1) { qa_db_user_login_sync(false); qa_set_logged_in_user($users[0]['userid'], $users[0]['handle'], false, $source); } else { $handle = qa_handle_make_valid(@$fields['handle']); if (strlen(@$fields['email'])) { // remove email address if it will cause a duplicate $emailusers = qa_db_user_find_by_email($fields['email']); if (count($emailusers)) { qa_redirect('login', array('e' => $fields['email'], 'ee' => '1')); unset($fields['email']); unset($fields['confirmed']); } } $userid = qa_create_new_user((string) @$fields['email'], null, $handle, isset($fields['level']) ? $fields['level'] : QA_USER_LEVEL_BASIC, @$fields['confirmed']); qa_db_user_login_add($userid, $source, $identifier); qa_db_user_login_sync(false); $profilefields = array('name', 'location', 'website', 'about'); foreach ($profilefields as $fieldname) { if (strlen(@$fields[$fieldname])) { qa_db_user_profile_set($userid, $fieldname, $fields[$fieldname]); } } if (strlen(@$fields['avatar'])) { qa_set_user_avatar($userid, $fields['avatar']); } qa_set_logged_in_user($userid, $handle, false, $source); } } }
More about this license: http://www.question2answer.org/license.php */ if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser header('Location: ../'); exit; } require_once QA_INCLUDE_DIR . 'qa-db-users.php'; require_once QA_INCLUDE_DIR . 'qa-app-format.php'; require_once QA_INCLUDE_DIR . 'qa-app-users.php'; require_once QA_INCLUDE_DIR . 'qa-db-selects.php'; require_once QA_INCLUDE_DIR . 'qa-util-image.php'; // Check we're not using single-sign on integration, that we're logged in if (QA_FINAL_EXTERNAL_USERS) { qa_fatal_error('User accounts are handled by external code'); } $userid = qa_get_logged_in_userid(); if (!isset($userid)) { qa_redirect('login'); } // Get current information on user list($useraccount, $userprofile, $userpoints, $userfields) = qa_db_select_with_pending(qa_db_user_account_selectspec($userid, true), qa_db_user_profile_selectspec($userid, true), qa_db_user_points_selectspec($userid, true), qa_db_userfields_selectspec()); $changehandle = qa_opt('allow_change_usernames') || !$userpoints['qposts'] && !$userpoints['aposts'] && !$userpoints['cposts']; $doconfirms = qa_opt('confirm_user_emails') && $useraccount['level'] < QA_USER_LEVEL_EXPERT; $isconfirmed = $useraccount['flags'] & QA_USER_FLAGS_EMAIL_CONFIRMED ? true : false; $haspassword = isset($useraccount['passsalt']) && isset($useraccount['passcheck']); $isblocked = qa_user_permit_error() ? true : false; // Process profile if saved if (qa_clicked('dosaveprofile') && !$isblocked) { require_once QA_INCLUDE_DIR . 'qa-app-users-edit.php';
function qa_limits_remaining($userid, $action) { if (qa_to_override(__FUNCTION__)) { $args = func_get_args(); return qa_call_override(__FUNCTION__, $args); } require_once QA_INCLUDE_DIR . 'qa-app-options.php'; require_once QA_INCLUDE_DIR . 'qa-db-limits.php'; $period = (int) (qa_opt('db_time') / 3600); $dblimits = qa_db_limits_get($userid, qa_remote_ip_address(), $action); switch ($action) { case QA_LIMIT_QUESTIONS: $userlimit = qa_opt('max_rate_user_qs'); $iplimit = qa_opt('max_rate_ip_qs'); break; case QA_LIMIT_ANSWERS: $userlimit = qa_opt('max_rate_user_as'); $iplimit = qa_opt('max_rate_ip_as'); break; case QA_LIMIT_COMMENTS: $userlimit = qa_opt('max_rate_user_cs'); $iplimit = qa_opt('max_rate_ip_cs'); break; case QA_LIMIT_VOTES: $userlimit = qa_opt('max_rate_user_votes'); $iplimit = qa_opt('max_rate_ip_votes'); break; case QA_LIMIT_REGISTRATIONS: $userlimit = 1; // not really relevant $iplimit = qa_opt('max_rate_ip_registers'); break; case QA_LIMIT_LOGINS: $userlimit = 1; // not really relevant $iplimit = qa_opt('max_rate_ip_logins'); break; case QA_LIMIT_UPLOADS: $userlimit = qa_opt('max_rate_user_uploads'); $iplimit = qa_opt('max_rate_ip_uploads'); break; case QA_LIMIT_FLAGS: $userlimit = qa_opt('max_rate_user_flags'); $iplimit = qa_opt('max_rate_ip_flags'); break; case QA_LIMIT_MESSAGES: $userlimit = qa_opt('max_rate_user_messages'); $iplimit = qa_opt('max_rate_ip_messages'); break; default: qa_fatal_error('Unknown limit code in qa_limits_remaining: ' . $action); break; } return max(0, min($userlimit - (@$dblimits['user']['period'] == $period ? $dblimits['user']['count'] : 0), $iplimit - (@$dblimits['ip']['period'] == $period ? $dblimits['ip']['count'] : 0))); }
function qa_post_content_to_text($content, $format) { $viewer = qa_load_viewer($content, $format); if (!isset($viewer)) { qa_fatal_error('Content could not be parsed in format: ' . $format); } return $viewer->get_text($content, $format, array()); }
function qa_complete_reset_user($userid) { if (qa_to_override(__FUNCTION__)) { $args = func_get_args(); return qa_call_override(__FUNCTION__, $args); } require_once QA_INCLUDE_DIR . 'util/string.php'; require_once QA_INCLUDE_DIR . 'app/options.php'; require_once QA_INCLUDE_DIR . 'app/emails.php'; require_once QA_INCLUDE_DIR . 'app/cookies.php'; require_once QA_INCLUDE_DIR . 'db/selects.php'; $password = qa_random_alphanum(max(QA_MIN_PASSWORD_LEN, QA_NEW_PASSWORD_LEN)); $userinfo = qa_db_select_with_pending(qa_db_user_account_selectspec($userid, true)); if (!qa_send_notification($userid, $userinfo['email'], $userinfo['handle'], qa_lang('emails/new_password_subject'), qa_lang('emails/new_password_body'), array('^password' => $password, '^url' => qa_opt('site_url')))) { qa_fatal_error('Could not send new password - password not reset'); } qa_db_user_set_password($userid, $password); // do this last, to be safe qa_db_user_set($userid, 'emailcode', ''); // so can't be reused qa_report_event('u_reset', $userid, $userinfo['handle'], qa_cookie_get(), array('email' => $userinfo['email'])); }
function qa_db_read_one_value($result, $allowempty = false) { if (!is_resource($result)) { qa_fatal_error('Reading one value from invalid result'); } $row = mysql_fetch_row($result); if (!is_array($row)) { if ($allowempty) { return null; } else { qa_fatal_error('Reading one value from empty results'); } } return $row[0]; }
function qa_comment_delete($oldcomment, $question, $answer, $userid, $handle, $cookieid) { if (!$oldcomment['hidden']) { qa_fatal_error('Tried to delete a non-hidden comment'); } qa_post_unindex($oldcomment['postid']); qa_db_post_delete($oldcomment['postid']); qa_db_points_update_ifuser($oldcomment['userid'], array('cposts')); qa_db_ccount_update(); qa_report_event('c_delete', $userid, $handle, $cookieid, array('postid' => $oldcomment['postid'], 'parentid' => $oldcomment['parentid'], 'parenttype' => isset($answer) ? $answer['basetype'] : $question['basetype'], 'questionid' => $question['postid'])); }
function qa_get_search_results($query, $start, $count, $userid, $absoluteurls, $fullcontent) { // Identify which search module should be used $searchmodules = qa_load_modules_with('search', 'process_search'); if (!count($searchmodules)) { qa_fatal_error('No search engine is available'); } $module = reset($searchmodules); // use first one by default if (count($searchmodules) > 1) { $tryname = qa_opt('search_module'); // use chosen one if it's available if (isset($searchmodules[$tryname])) { $module = $searchmodules[$tryname]; } } // Get the results $results = $module->process_search($query, $start, $count, $userid, $absoluteurls, $fullcontent); // Work out what additional information (if any) we need to retrieve for the results $keypostidgetfull = array(); $keypostidgettype = array(); $keypostidgetquestion = array(); $keypageidgetpage = array(); foreach ($results as $result) { if (isset($result['question_postid']) && !isset($result['question'])) { $keypostidgetfull[$result['question_postid']] = true; } if (isset($result['match_postid'])) { if (!(isset($result['question_postid']) || isset($result['question']))) { $keypostidgetquestion[$result['match_postid']] = true; } elseif (!isset($result['match_type'])) { $keypostidgettype[$result['match_postid']] = true; } } if (isset($result['page_pageid']) && !isset($result['page'])) { $keypageidgetpage[$result['page_pageid']] = true; } } // Perform the appropriate database queries list($postidfull, $postidtype, $postidquestion, $pageidpage) = qa_db_select_with_pending(count($keypostidgetfull) ? qa_db_posts_selectspec($userid, array_keys($keypostidgetfull), $fullcontent) : null, count($keypostidgettype) ? qa_db_posts_basetype_selectspec(array_keys($keypostidgettype)) : null, count($keypostidgetquestion) ? qa_db_posts_to_qs_selectspec($userid, array_keys($keypostidgetquestion), $fullcontent) : null, count($keypageidgetpage) ? qa_db_pages_selectspec(null, array_keys($keypageidgetpage)) : null); // Supplement the results as appropriate foreach ($results as $key => $result) { if (isset($result['question_postid']) && !isset($result['question'])) { if (@$postidfull[$result['question_postid']]['basetype'] == 'Q') { $result['question'] = @$postidfull[$result['question_postid']]; } } if (isset($result['match_postid'])) { if (!(isset($result['question_postid']) || isset($result['question']))) { $result['question'] = @$postidquestion[$result['match_postid']]; if (!isset($result['match_type'])) { $result['match_type'] = @$result['question']['obasetype']; } } elseif (!isset($result['match_type'])) { $result['match_type'] = @$postidtype[$result['match_postid']]; } } if (isset($result['question']) && !isset($result['question_postid'])) { $result['question_postid'] = $result['question']['postid']; } if (isset($result['page_pageid']) && !isset($result['page'])) { $result['page'] = @$pageidpage[$result['page_pageid']]; } if (!isset($result['title'])) { if (isset($result['question'])) { $result['title'] = $result['question']['title']; } elseif (isset($result['page'])) { $result['title'] = $result['page']['heading']; } } if (!isset($result['url'])) { if (isset($result['question'])) { $result['url'] = qa_q_path($result['question']['postid'], $result['question']['title'], $absoluteurls, @$result['match_type'], @$result['match_postid']); } elseif (isset($result['page'])) { $result['url'] = qa_path($result['page']['tags'], null, qa_opt('site_url')); } } $results[$key] = $result; } // Return the results return $results; }
function qa_limits_calc_remaining($action, $userlimits, $iplimits) { switch ($action) { case QA_LIMIT_QUESTIONS: $usermax = qa_opt('max_rate_user_qs'); $ipmax = qa_opt('max_rate_ip_qs'); break; case QA_LIMIT_ANSWERS: $usermax = qa_opt('max_rate_user_as'); $ipmax = qa_opt('max_rate_ip_as'); break; case QA_LIMIT_COMMENTS: $usermax = qa_opt('max_rate_user_cs'); $ipmax = qa_opt('max_rate_ip_cs'); break; case QA_LIMIT_VOTES: $usermax = qa_opt('max_rate_user_votes'); $ipmax = qa_opt('max_rate_ip_votes'); break; case QA_LIMIT_REGISTRATIONS: $usermax = 1; // not really relevant $ipmax = qa_opt('max_rate_ip_registers'); break; case QA_LIMIT_LOGINS: $usermax = 1; // not really relevant $ipmax = qa_opt('max_rate_ip_logins'); break; case QA_LIMIT_UPLOADS: $usermax = qa_opt('max_rate_user_uploads'); $ipmax = qa_opt('max_rate_ip_uploads'); break; case QA_LIMIT_FLAGS: $usermax = qa_opt('max_rate_user_flags'); $ipmax = qa_opt('max_rate_ip_flags'); break; case QA_LIMIT_MESSAGES: case QA_LIMIT_WALL_POSTS: $usermax = qa_opt('max_rate_user_messages'); $ipmax = qa_opt('max_rate_ip_messages'); break; default: qa_fatal_error('Unknown limit code in qa_limits_calc_remaining: ' . $action); break; } $period = (int) (qa_opt('db_time') / 3600); return max(0, min($usermax - (@$userlimits['period'] == $period ? $userlimits['count'] : 0), $ipmax - (@$iplimits['period'] == $period ? $iplimits['count'] : 0))); }
function qa_editor_load_field($editor, &$qa_content, $content, $format, $fieldname, $rows, $focusnow = false, $loadnow = true) { if (!isset($editor)) { qa_fatal_error('No editor found for format: ' . $format); } $field = $editor->get_field($qa_content, $content, $format, $fieldname, $rows, $focusnow); $onloads = array(); if ($loadnow && method_exists($editor, 'load_script')) { $onloads[] = $editor->load_script($fieldname); } if ($focusnow && method_exists($editor, 'focus_script')) { $onloads[] = $editor->focus_script($fieldname); } if (count($onloads)) { $qa_content['script_onloads'][] = $onloads; } return $field; }
for ($attempt = 0; $attempt < 1000; $attempt++) { $suffix = $attempt ? '-' . (1 + $attempt) : ''; $newtag = qa_substr(implode('-', qa_string_to_words($inname)), 0, QA_DB_MAX_PROFILE_TITLE_LENGTH - strlen($suffix)) . $suffix; $uniquetag = true; foreach ($userfields as $userfield) { if (qa_strtolower(trim($newtag)) == qa_strtolower(trim($userfield['title']))) { $uniquetag = false; } } if ($uniquetag) { $fieldid = qa_db_userfield_create($newtag, $inname, $inflags); qa_db_userfield_move($fieldid, $inposition); qa_redirect('admin/users'); } } qa_fatal_error('Could not create a unique database tag'); } } } // Prepare content for theme $qa_content = qa_content_prepare(); $qa_content['title'] = qa_lang_html('admin/admin_title') . ' - ' . qa_lang_html('admin/users_title'); $qa_content['error'] = qa_admin_page_error(); $positionoptions = array(); $previous = null; $passedself = false; foreach ($userfields as $userfield) { if (isset($previous)) { $positionhtml = qa_lang_html_sub('admin/after_x', qa_html(qa_user_userfield_label($passedself ? $userfield : $previous))); } else { $positionhtml = qa_lang_html('admin/first');
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. More about this license: http://www.question2answer.org/license.php */ if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser header('Location: ../'); exit; } require_once QA_INCLUDE_DIR . 'qa-app-captcha.php'; require_once QA_INCLUDE_DIR . 'qa-db-users.php'; // Check we're not using single-sign on integration, that we're not logged in, and we're not blocked if (QA_FINAL_EXTERNAL_USERS) { qa_fatal_error('User registration is handled by external code'); } if (qa_is_logged_in()) { qa_redirect(''); } if (qa_opt('suspend_register_users')) { $qa_content = qa_content_prepare(); $qa_content['error'] = qa_lang_html('users/register_suspended'); return $qa_content; } if (qa_user_permit_error()) { $qa_content = qa_content_prepare(); $qa_content['error'] = qa_lang_html('users/no_permission'); return $qa_content; } // Process submitted form
function qa_lang_html_sub_split($identifier, $htmlparam, $symbol = '^') { $html = qa_lang_html($identifier); $symbolpos = strpos($html, $symbol); if (!is_numeric($symbolpos)) { qa_fatal_error('Missing ' . $symbol . ' in language string ' . $identifier); } return array('prefix' => substr($html, 0, $symbolpos), 'data' => $htmlparam, 'suffix' => substr($html, $symbolpos + 1)); }
function qa_log_in_external_user($source, $identifier, $fields) { require_once QA_INCLUDE_DIR . 'qa-db-users.php'; $users = qa_db_user_login_find($source, $identifier); $countusers = count($users); if ($countusers > 1) { qa_fatal_error('External login mapped to more than one user'); } // should never happen if ($countusers) { // user exists so log them in qa_set_logged_in_user($users[0]['userid'], $users[0]['handle'], false, $source); } else { // create and log in user require_once QA_INCLUDE_DIR . 'qa-app-users-edit.php'; $handle = qa_handle_make_valid(@$fields['handle']); $userid = qa_create_new_user((string) @$fields['email'], null, $handle, isset($fields['level']) ? $fields['level'] : QA_USER_LEVEL_BASIC, @$fields['confirmed']); qa_db_user_login_add($userid, $source, $identifier); $profilefields = array('name', 'location', 'website', 'about'); foreach ($profilefields as $fieldname) { if (strlen(@$fields[$fieldname])) { qa_db_user_profile_set($userid, $fieldname, $fields[$fieldname]); } } if (strlen(@$fields['avatar'])) { qa_set_user_avatar($userid, $fields['avatar']); } qa_set_logged_in_user($userid, $handle, false, $source); } }
function qa_comment_delete($oldcomment, $question, $parent, $userid, $handle, $cookieid) { if (!isset($parent)) { $parent = $question; } // for backwards compatibility with old answer parameter if ($oldcomment['type'] != 'C_HIDDEN') { qa_fatal_error('Tried to delete a non-hidden comment'); } qa_post_unindex($oldcomment['postid']); qa_db_post_delete($oldcomment['postid']); qa_db_points_update_ifuser($oldcomment['userid'], array('cposts')); qa_db_ccount_update(); qa_report_event('c_delete', $userid, $handle, $cookieid, array('postid' => $oldcomment['postid'], 'parentid' => $oldcomment['parentid'], 'oldcomment' => $oldcomment, 'parenttype' => $parent['basetype'], 'questionid' => $question['postid'])); }
function qa_get_logged_in_user_field($field) { if (qa_to_override(__FUNCTION__)) { $args = func_get_args(); return qa_call_override(__FUNCTION__, $args); } global $qa_cached_logged_in_user; $userid = qa_get_logged_in_userid(); if (isset($userid) && !isset($qa_cached_logged_in_user)) { require_once QA_INCLUDE_DIR . 'qa-db-selects.php'; $qa_cached_logged_in_user = qa_db_get_pending_result('loggedinuser', qa_db_user_account_selectspec($userid, true)); if (!isset($qa_cached_logged_in_user)) { // the user can no longer be found (should be because they're deleted) qa_clear_session_user(); qa_fatal_error('The logged in user cannot be found'); // it's too late here to proceed because the caller may already be branching based on whether someone is logged in } } return @$qa_cached_logged_in_user[$field]; }
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. More about this license: http://www.question2answer.org/license.php */ if (!defined('QA_VERSION')) { // don't allow this page to be requested directly from browser header('Location: ../'); exit; } // Check we're not using Q2A's single-sign on integration and that we're not logged in if (QA_FINAL_EXTERNAL_USERS) { qa_fatal_error('User login is handled by external code'); } if (qa_is_logged_in()) { qa_redirect(''); } // Process submitted form after checking we haven't reached rate limit $passwordsent = qa_get('ps'); if (qa_clicked('dologin')) { require_once QA_INCLUDE_DIR . 'qa-app-limits.php'; if (qa_limits_remaining(null, QA_LIMIT_LOGINS)) { require_once QA_INCLUDE_DIR . 'qa-db-users.php'; require_once QA_INCLUDE_DIR . 'qa-db-selects.php'; qa_limits_increment(null, QA_LIMIT_LOGINS); $inemailhandle = qa_post_text('emailhandle'); $inpassword = qa_post_text('password'); $inremember = qa_post_text('remember');
function qa_db_qs_selectspec($voteuserid, $sort, $start, $categoryslugs = null, $createip = null, $specialtype = false, $full = false, $count = null) { if ($specialtype == 'Q' || $specialtype == 'Q_QUEUED') { $type = $specialtype; } else { $type = $specialtype ? 'Q_HIDDEN' : 'Q'; } // for backwards compatibility $count = isset($count) ? min($count, QA_DB_RETRIEVE_QS_AS) : QA_DB_RETRIEVE_QS_AS; switch ($sort) { case 'acount': case 'flagcount': case 'netvotes': case 'views': $sortsql = 'ORDER BY ^posts.' . $sort . ' DESC, ^posts.created DESC'; break; case 'created': case 'hotness': $sortsql = 'ORDER BY ^posts.' . $sort . ' DESC'; break; default: qa_fatal_error('qa_db_qs_selectspec() called with illegal sort value'); break; } $selectspec = qa_db_posts_basic_selectspec($voteuserid, $full); $selectspec['source'] .= " JOIN (SELECT postid FROM ^posts WHERE " . qa_db_categoryslugs_sql_args($categoryslugs, $selectspec['arguments']) . (isset($createip) ? "createip=INET_ATON(\$) AND " : "") . "type=\$ " . $sortsql . " LIMIT #,#) y ON ^posts.postid=y.postid"; if (isset($createip)) { $selectspec['arguments'][] = $createip; } array_push($selectspec['arguments'], $type, $start, $count); $selectspec['sortdesc'] = $sort; return $selectspec; }
function qa_db_upgrade_tables() { require_once QA_INCLUDE_DIR . 'app/recalc.php'; $definitions = qa_db_table_definitions(); $keyrecalc = array(); // Write-lock all Q2A tables before we start so no one can read or write anything $keydbtables = qa_array_to_keys(qa_db_list_tables()); foreach ($definitions as $rawname => $definition) { if (isset($keydbtables[qa_db_add_table_prefix($rawname)])) { $locks[] = '^' . $rawname . ' WRITE'; } } $locktablesquery = 'LOCK TABLES ' . implode(', ', $locks); qa_db_upgrade_query($locktablesquery); // Upgrade it step-by-step until it's up to date (do LOCK TABLES after ALTER TABLE because the lock can sometimes be lost) while (1) { $version = qa_db_get_db_version(); if ($version >= QA_DB_VERSION_CURRENT) { break; } $newversion = $version + 1; qa_db_upgrade_progress(QA_DB_VERSION_CURRENT - $version . ' upgrade step/s remaining...'); switch ($newversion) { // Up to here: Version 1.0 beta 1 case 2: qa_db_upgrade_query('ALTER TABLE ^posts DROP COLUMN votes, ADD COLUMN upvotes ' . $definitions['posts']['upvotes'] . ' AFTER cookieid, ADD COLUMN downvotes ' . $definitions['posts']['downvotes'] . ' AFTER upvotes'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecountposts'] = true; break; case 3: qa_db_upgrade_query('ALTER TABLE ^userpoints ADD COLUMN upvoteds ' . $definitions['userpoints']['upvoteds'] . ' AFTER avoteds, ADD COLUMN downvoteds ' . $definitions['userpoints']['downvoteds'] . ' AFTER upvoteds'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecalcpoints'] = true; break; case 4: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN lastuserid ' . $definitions['posts']['lastuserid'] . ' AFTER cookieid, CHANGE COLUMN updated updated ' . $definitions['posts']['updated']); qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('UPDATE ^posts SET updated=NULL WHERE updated=0 OR updated=created'); break; case 5: qa_db_upgrade_query('ALTER TABLE ^contentwords ADD COLUMN type ' . $definitions['contentwords']['type'] . ' AFTER count, ADD COLUMN questionid ' . $definitions['contentwords']['questionid'] . ' AFTER type'); qa_db_upgrade_query($locktablesquery); $keyrecalc['doreindexcontent'] = true; break; // Up to here: Version 1.0 beta 2 // Up to here: Version 1.0 beta 2 case 6: qa_db_upgrade_query('ALTER TABLE ^userpoints ADD COLUMN cposts ' . $definitions['userpoints']['cposts'] . ' AFTER aposts'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecalcpoints'] = true; break; case 7: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN sessioncode ' . $definitions['users']['sessioncode'] . ' AFTER writeip'); qa_db_upgrade_query($locktablesquery); } break; case 8: qa_db_upgrade_query('ALTER TABLE ^posts ADD KEY (type, acount, created)'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecountposts'] = true; // for unanswered question count break; // Up to here: Version 1.0 beta 3, 1.0, 1.0.1 beta, 1.0.1 // Up to here: Version 1.0 beta 3, 1.0, 1.0.1 beta, 1.0.1 case 9: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query('ALTER TABLE ^users CHANGE COLUMN resetcode emailcode ' . $definitions['users']['emailcode'] . ', ADD COLUMN flags ' . $definitions['users']['flags'] . ' AFTER sessioncode'); qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('UPDATE ^users SET flags=1'); } break; case 10: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('categories', array('categoryid' => $definitions['categories']['categoryid'], 'title' => $definitions['categories']['title'], 'tags' => $definitions['categories']['tags'], 'qcount' => $definitions['categories']['qcount'], 'position' => $definitions['categories']['position'], 'PRIMARY KEY (categoryid)', 'UNIQUE tags (tags)', 'UNIQUE position (position)'))); // hard-code list of columns and indexes to ensure we ignore any added at a later stage $locktablesquery .= ', ^categories WRITE'; qa_db_upgrade_query($locktablesquery); break; case 11: qa_db_upgrade_query('ALTER TABLE ^posts ADD CONSTRAINT ^posts_ibfk_2 FOREIGN KEY (parentid) REFERENCES ^posts(postid), ADD COLUMN categoryid ' . $definitions['posts']['categoryid'] . ' AFTER parentid, ADD KEY categoryid (categoryid, type, created), ADD CONSTRAINT ^posts_ibfk_3 FOREIGN KEY (categoryid) REFERENCES ^categories(categoryid) ON DELETE SET NULL'); // foreign key on parentid important now that deletion is possible qa_db_upgrade_query($locktablesquery); break; case 12: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('pages', array('pageid' => $definitions['pages']['pageid'], 'title' => $definitions['pages']['title'], 'nav' => $definitions['pages']['nav'], 'position' => $definitions['pages']['position'], 'flags' => $definitions['pages']['flags'], 'tags' => $definitions['pages']['tags'], 'heading' => $definitions['pages']['heading'], 'content' => $definitions['pages']['content'], 'PRIMARY KEY (pageid)', 'UNIQUE tags (tags)', 'UNIQUE position (position)'))); // hard-code list of columns and indexes to ensure we ignore any added at a later stage $locktablesquery .= ', ^pages WRITE'; qa_db_upgrade_query($locktablesquery); break; case 13: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN createip ' . $definitions['posts']['createip'] . ' AFTER cookieid, ADD KEY createip (createip, created)'); qa_db_upgrade_query($locktablesquery); break; case 14: qa_db_upgrade_query('ALTER TABLE ^userpoints DROP COLUMN qvotes, DROP COLUMN avotes, ADD COLUMN qupvotes ' . $definitions['userpoints']['qupvotes'] . ' AFTER aselecteds, ADD COLUMN qdownvotes ' . $definitions['userpoints']['qdownvotes'] . ' AFTER qupvotes, ADD COLUMN aupvotes ' . $definitions['userpoints']['aupvotes'] . ' AFTER qdownvotes, ADD COLUMN adownvotes ' . $definitions['userpoints']['adownvotes'] . ' AFTER aupvotes'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecalcpoints'] = true; break; // Up to here: Version 1.2 beta 1 // Up to here: Version 1.2 beta 1 case 15: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_table_columns($definitions, 'users', array('emailcode', 'sessioncode', 'flags')); } qa_db_upgrade_table_columns($definitions, 'posts', array('acount', 'upvotes', 'downvotes', 'format')); qa_db_upgrade_table_columns($definitions, 'categories', array('qcount')); qa_db_upgrade_table_columns($definitions, 'words', array('titlecount', 'contentcount', 'tagcount')); qa_db_upgrade_table_columns($definitions, 'userpoints', array('points', 'qposts', 'aposts', 'cposts', 'aselects', 'aselecteds', 'qupvotes', 'qdownvotes', 'aupvotes', 'adownvotes', 'qvoteds', 'avoteds', 'upvoteds', 'downvoteds')); qa_db_upgrade_query($locktablesquery); break; // Up to here: Version 1.2 (release) // Up to here: Version 1.2 (release) case 16: qa_db_upgrade_table_columns($definitions, 'posts', array('format')); qa_db_upgrade_query($locktablesquery); $keyrecalc['doreindexcontent'] = true; // because of new treatment of apostrophes in words break; case 17: qa_db_upgrade_query('ALTER TABLE ^posts ADD KEY updated (updated, type), ADD KEY categoryid_2 (categoryid, updated, type)'); qa_db_upgrade_query($locktablesquery); break; case 18: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN lastip ' . $definitions['posts']['lastip'] . ' AFTER lastuserid, ADD KEY lastip (lastip, updated, type)'); qa_db_upgrade_query($locktablesquery); break; case 19: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN avatarblobid ' . $definitions['users']['avatarblobid'] . ' AFTER handle, ADD COLUMN avatarwidth ' . $definitions['users']['avatarwidth'] . ' AFTER avatarblobid, ADD COLUMN avatarheight ' . $definitions['users']['avatarheight'] . ' AFTER avatarwidth'); } // hard-code list of columns and indexes to ensure we ignore any added at a later stage qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('blobs', array('blobid' => $definitions['blobs']['blobid'], 'format' => $definitions['blobs']['format'], 'content' => $definitions['blobs']['content'], 'PRIMARY KEY (blobid)'))); qa_db_upgrade_query(qa_db_create_table_sql('cache', array('type' => $definitions['cache']['type'], 'cacheid' => $definitions['cache']['cacheid'], 'content' => $definitions['cache']['content'], 'created' => $definitions['cache']['created'], 'lastread' => $definitions['cache']['lastread'], 'PRIMARY KEY (type,cacheid)', 'KEY (lastread)'))); // hard-code list of columns and indexes to ensure we ignore any added at a later stage $locktablesquery .= ', ^blobs WRITE, ^cache WRITE'; qa_db_upgrade_query($locktablesquery); break; case 20: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('userlogins', array('userid' => $definitions['userlogins']['userid'], 'source' => $definitions['userlogins']['source'], 'identifier' => $definitions['userlogins']['identifier'], 'identifiermd5' => $definitions['userlogins']['identifiermd5'], 'KEY source (source, identifiermd5)', 'KEY userid (userid)', 'CONSTRAINT ^userlogins_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE'))); qa_db_upgrade_query('ALTER TABLE ^users CHANGE COLUMN passsalt passsalt ' . $definitions['users']['passsalt'] . ', CHANGE COLUMN passcheck passcheck ' . $definitions['users']['passcheck']); $locktablesquery .= ', ^userlogins WRITE'; qa_db_upgrade_query($locktablesquery); } break; case 21: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('userfields', array('fieldid' => $definitions['userfields']['fieldid'], 'title' => $definitions['userfields']['title'], 'content' => $definitions['userfields']['content'], 'position' => $definitions['userfields']['position'], 'flags' => $definitions['userfields']['flags'], 'PRIMARY KEY (fieldid)'))); $locktablesquery .= ', ^userfields WRITE'; qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query(qa_db_default_userfields_sql()); } break; // Up to here: Version 1.3 beta 1 // Up to here: Version 1.3 beta 1 case 22: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN sessionsource ' . $definitions['users']['sessionsource'] . ' AFTER sessioncode'); qa_db_upgrade_query($locktablesquery); } break; // Up to here: Version 1.3 beta 2 and release // Up to here: Version 1.3 beta 2 and release case 23: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('widgets', array('widgetid' => $definitions['widgets']['widgetid'], 'place' => $definitions['widgets']['place'], 'position' => $definitions['widgets']['position'], 'tags' => $definitions['widgets']['tags'], 'title' => $definitions['widgets']['title'], 'PRIMARY KEY (widgetid)', 'UNIQUE position (position)'))); $locktablesquery .= ', ^widgets WRITE'; qa_db_upgrade_query($locktablesquery); break; case 24: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('tagwords', array('postid' => $definitions['tagwords']['postid'], 'wordid' => $definitions['tagwords']['wordid'], 'KEY postid (postid)', 'KEY wordid (wordid)', 'CONSTRAINT ^tagwords_ibfk_1 FOREIGN KEY (postid) REFERENCES ^posts(postid) ON DELETE CASCADE', 'CONSTRAINT ^tagwords_ibfk_2 FOREIGN KEY (wordid) REFERENCES ^words(wordid)'))); $locktablesquery .= ', ^tagwords WRITE'; qa_db_upgrade_query('ALTER TABLE ^words ADD COLUMN tagwordcount ' . $definitions['words']['tagwordcount'] . ' AFTER contentcount'); qa_db_upgrade_query($locktablesquery); $keyrecalc['doreindexcontent'] = true; break; // Up to here: Version 1.4 developer preview // Up to here: Version 1.4 developer preview case 25: $keycolumns = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^blobs'))); // might be using blobs table shared with another installation, so check if we need to upgrade if (isset($keycolumns['filename'])) { qa_db_upgrade_progress('Skipping upgrading blobs table since it was already upgraded by another Q2A site sharing it.'); } else { qa_db_upgrade_query('ALTER TABLE ^blobs ADD COLUMN filename ' . $definitions['blobs']['filename'] . ' AFTER content, ADD COLUMN userid ' . $definitions['blobs']['userid'] . ' AFTER filename, ADD COLUMN cookieid ' . $definitions['blobs']['cookieid'] . ' AFTER userid, ADD COLUMN createip ' . $definitions['blobs']['createip'] . ' AFTER cookieid, ADD COLUMN created ' . $definitions['blobs']['created'] . ' AFTER createip'); qa_db_upgrade_query($locktablesquery); } break; case 26: qa_db_upgrade_query('ALTER TABLE ^uservotes ADD COLUMN flag ' . $definitions['uservotes']['flag'] . ' AFTER vote'); qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN flagcount ' . $definitions['posts']['flagcount'] . ' AFTER downvotes, ADD KEY type_3 (type, flagcount, created)'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecountposts'] = true; break; case 27: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN netvotes ' . $definitions['posts']['netvotes'] . ' AFTER downvotes, ADD KEY type_4 (type, netvotes, created)'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecountposts'] = true; break; case 28: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN views ' . $definitions['posts']['views'] . ' AFTER netvotes, ADD COLUMN hotness ' . $definitions['posts']['hotness'] . ' AFTER views, ADD KEY type_5 (type, views, created), ADD KEY type_6 (type, hotness)'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecountposts'] = true; break; case 29: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN lastviewip ' . $definitions['posts']['lastviewip'] . ' AFTER netvotes'); qa_db_upgrade_query($locktablesquery); break; case 30: qa_db_upgrade_query('ALTER TABLE ^posts DROP FOREIGN KEY ^posts_ibfk_3'); // to allow category column types to be changed qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('ALTER TABLE ^posts DROP KEY categoryid, DROP KEY categoryid_2'); qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('ALTER TABLE ^categories CHANGE COLUMN categoryid categoryid ' . $definitions['categories']['categoryid'] . ', ADD COLUMN parentid ' . $definitions['categories']['parentid'] . ' AFTER categoryid, ADD COLUMN backpath ' . $definitions['categories']['backpath'] . ' AFTER position, ADD COLUMN content ' . $definitions['categories']['content'] . ' AFTER tags, DROP INDEX tags, DROP INDEX position, ADD UNIQUE parentid (parentid, tags), ADD UNIQUE parentid_2 (parentid, position), ADD KEY backpath (backpath(' . QA_DB_MAX_CAT_PAGE_TAGS_LENGTH . '))'); qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('ALTER TABLE ^posts CHANGE COLUMN categoryid categoryid ' . $definitions['posts']['categoryid'] . ', ADD COLUMN catidpath1 ' . $definitions['posts']['catidpath1'] . ' AFTER categoryid, ADD COLUMN catidpath2 ' . $definitions['posts']['catidpath2'] . ' AFTER catidpath1, ADD COLUMN catidpath3 ' . $definitions['posts']['catidpath3'] . ' AFTER catidpath2'); // QA_CATEGORY_DEPTH=4 qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('ALTER TABLE ^posts ADD KEY catidpath1 (catidpath1, type, created), ADD KEY catidpath2 (catidpath2, type, created), ADD KEY catidpath3 (catidpath3, type, created), ADD KEY categoryid (categoryid, type, created), ADD KEY catidpath1_2 (catidpath1, updated, type), ADD KEY catidpath2_2 (catidpath2, updated, type), ADD KEY catidpath3_2 (catidpath3, updated, type), ADD KEY categoryid_2 (categoryid, updated, type)'); qa_db_upgrade_query($locktablesquery); qa_db_upgrade_query('ALTER TABLE ^posts ADD CONSTRAINT ^posts_ibfk_3 FOREIGN KEY (categoryid) REFERENCES ^categories(categoryid) ON DELETE SET NULL'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecalccategories'] = true; break; // Up to here: Version 1.4 betas and release // Up to here: Version 1.4 betas and release case 31: qa_db_upgrade_query('ALTER TABLE ^posts CHANGE COLUMN type type ' . $definitions['posts']['type'] . ', ADD COLUMN updatetype ' . $definitions['posts']['updatetype'] . ' AFTER updated, ADD COLUMN closedbyid ' . $definitions['posts']['closedbyid'] . ' AFTER selchildid, ADD KEY closedbyid (closedbyid), ADD CONSTRAINT ^posts_ibfk_4 FOREIGN KEY (closedbyid) REFERENCES ^posts(postid)'); qa_db_upgrade_query($locktablesquery); break; case 32: qa_db_upgrade_query("UPDATE ^posts SET updatetype=IF(INSTR(type, '_HIDDEN')>0, 'H', 'E') WHERE updated IS NOT NULL"); break; case 33: qa_db_upgrade_query('ALTER TABLE ^contentwords CHANGE COLUMN type type ' . $definitions['contentwords']['type']); qa_db_upgrade_query($locktablesquery); break; case 34: if (!QA_FINAL_EXTERNAL_USERS) { $keytables = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW TABLES'))); // might be using messages table shared with another installation, so check if we need to upgrade if (isset($keytables[qa_db_add_table_prefix('messages')])) { qa_db_upgrade_progress('Skipping messages table since it was already added by another Q2A site sharing these users.'); } else { qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('messages', array('messageid' => $definitions['messages']['messageid'], 'fromuserid' => $definitions['messages']['fromuserid'], 'touserid' => $definitions['messages']['touserid'], 'content' => $definitions['messages']['content'], 'format' => $definitions['messages']['format'], 'created' => $definitions['messages']['created'], 'PRIMARY KEY (messageid)', 'KEY fromuserid (fromuserid, touserid, created)'))); $locktablesquery .= ', ^messages WRITE'; qa_db_upgrade_query($locktablesquery); } } break; case 35: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('userfavorites', array('userid' => $definitions['userfavorites']['userid'], 'entitytype' => $definitions['userfavorites']['entitytype'], 'entityid' => $definitions['userfavorites']['entityid'], 'nouserevents' => $definitions['userfavorites']['nouserevents'], 'PRIMARY KEY (userid, entitytype, entityid)', 'KEY userid (userid, nouserevents)', 'KEY entitytype (entitytype, entityid, nouserevents)', QA_FINAL_EXTERNAL_USERS ? null : 'CONSTRAINT ^userfavorites_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE'))); $locktablesquery .= ', ^userfavorites WRITE'; qa_db_upgrade_query($locktablesquery); break; case 36: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('userevents', array('userid' => $definitions['userevents']['userid'], 'entitytype' => $definitions['userevents']['entitytype'], 'entityid' => $definitions['userevents']['entityid'], 'questionid' => $definitions['userevents']['questionid'], 'lastpostid' => $definitions['userevents']['lastpostid'], 'updatetype' => $definitions['userevents']['updatetype'], 'lastuserid' => $definitions['userevents']['lastuserid'], 'updated' => $definitions['userevents']['updated'], 'KEY userid (userid, updated)', 'KEY questionid (questionid, userid)', QA_FINAL_EXTERNAL_USERS ? null : 'CONSTRAINT ^userevents_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE'))); $locktablesquery .= ', ^userevents WRITE'; qa_db_upgrade_query($locktablesquery); $keyrecalc['dorefillevents'] = true; break; case 37: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('sharedevents', array('entitytype' => $definitions['sharedevents']['entitytype'], 'entityid' => $definitions['sharedevents']['entityid'], 'questionid' => $definitions['sharedevents']['questionid'], 'lastpostid' => $definitions['sharedevents']['lastpostid'], 'updatetype' => $definitions['sharedevents']['updatetype'], 'lastuserid' => $definitions['sharedevents']['lastuserid'], 'updated' => $definitions['sharedevents']['updated'], 'KEY entitytype (entitytype, entityid, updated)', 'KEY questionid (questionid, entitytype, entityid)'))); $locktablesquery .= ', ^sharedevents WRITE'; qa_db_upgrade_query($locktablesquery); $keyrecalc['dorefillevents'] = true; break; case 38: qa_db_upgrade_query('ALTER TABLE ^posts ADD KEY lastuserid (lastuserid, updated, type)'); qa_db_upgrade_query($locktablesquery); break; case 39: qa_db_upgrade_query('ALTER TABLE ^posts DROP KEY type_3, ADD KEY flagcount (flagcount, created, type)'); qa_db_upgrade_query($locktablesquery); break; case 40: qa_db_upgrade_query('ALTER TABLE ^userpoints ADD COLUMN bonus ' . $definitions['userpoints']['bonus'] . ' AFTER downvoteds'); qa_db_upgrade_query($locktablesquery); break; case 41: qa_db_upgrade_query('ALTER TABLE ^pages ADD COLUMN permit ' . $definitions['pages']['permit'] . ' AFTER flags'); qa_db_upgrade_query($locktablesquery); break; case 42: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('usermetas', array('userid' => $definitions['usermetas']['userid'], 'title' => $definitions['usermetas']['title'], 'content' => $definitions['usermetas']['content'], 'PRIMARY KEY (userid, title)', QA_FINAL_EXTERNAL_USERS ? null : 'CONSTRAINT ^usermetas_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE'))); $locktablesquery .= ', ^usermetas WRITE'; qa_db_upgrade_query($locktablesquery); break; case 43: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('postmetas', array('postid' => $definitions['postmetas']['postid'], 'title' => $definitions['postmetas']['title'], 'content' => $definitions['postmetas']['content'], 'PRIMARY KEY (postid, title)', 'CONSTRAINT ^postmetas_ibfk_1 FOREIGN KEY (postid) REFERENCES ^posts(postid) ON DELETE CASCADE'))); $locktablesquery .= ', ^postmetas WRITE'; qa_db_upgrade_query($locktablesquery); break; case 44: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('categorymetas', array('categoryid' => $definitions['categorymetas']['categoryid'], 'title' => $definitions['categorymetas']['title'], 'content' => $definitions['categorymetas']['content'], 'PRIMARY KEY (categoryid, title)', 'CONSTRAINT ^categorymetas_ibfk_1 FOREIGN KEY (categoryid) REFERENCES ^categories(categoryid) ON DELETE CASCADE'))); $locktablesquery .= ', ^categorymetas WRITE'; qa_db_upgrade_query($locktablesquery); break; case 45: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('tagmetas', array('tag' => $definitions['tagmetas']['tag'], 'title' => $definitions['tagmetas']['title'], 'content' => $definitions['tagmetas']['content'], 'PRIMARY KEY (tag, title)'))); $locktablesquery .= ', ^tagmetas WRITE'; qa_db_upgrade_query($locktablesquery); break; case 46: qa_db_upgrade_query('ALTER TABLE ^posts DROP KEY selchildid, ADD KEY selchildid (selchildid, type, created), ADD COLUMN amaxvote SMALLINT UNSIGNED NOT NULL DEFAULT 0 AFTER acount, ADD KEY type_7 (type, amaxvote, created)'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecountposts'] = true; break; case 47: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query(qa_db_create_table_sql('usernotices', array('noticeid' => $definitions['usernotices']['noticeid'], 'userid' => $definitions['usernotices']['userid'], 'content' => $definitions['usernotices']['content'], 'format' => $definitions['usernotices']['format'], 'tags' => $definitions['usernotices']['tags'], 'created' => $definitions['usernotices']['created'], 'PRIMARY KEY (noticeid)', 'KEY userid (userid, created)', QA_FINAL_EXTERNAL_USERS ? null : 'CONSTRAINT ^usernotices_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE'))); $locktablesquery .= ', ^usernotices WRITE'; qa_db_upgrade_query($locktablesquery); break; // Up to here: Version 1.5.x // Up to here: Version 1.5.x case 48: if (!QA_FINAL_EXTERNAL_USERS) { $keycolumns = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^messages'))); // might be using messages table shared with another installation, so check if we need to upgrade if (isset($keycolumns['type'])) { qa_db_upgrade_progress('Skipping upgrading messages table since it was already upgraded by another Q2A site sharing it.'); } else { qa_db_upgrade_query('ALTER TABLE ^messages ADD COLUMN type ' . $definitions['messages']['type'] . ' AFTER messageid, DROP KEY fromuserid, ADD key type (type, fromuserid, touserid, created), ADD KEY touserid (touserid, type, created)'); qa_db_upgrade_query($locktablesquery); } } break; case 49: if (!QA_FINAL_EXTERNAL_USERS) { qa_db_upgrade_query('ALTER TABLE ^users CHANGE COLUMN flags flags ' . $definitions['users']['flags']); qa_db_upgrade_query($locktablesquery); } break; case 50: qa_db_upgrade_query('ALTER TABLE ^posts ADD COLUMN name ' . $definitions['posts']['name'] . ' AFTER tags'); qa_db_upgrade_query($locktablesquery); break; case 51: if (!QA_FINAL_EXTERNAL_USERS) { $keycolumns = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^userfields'))); // might be using userfields table shared with another installation, so check if we need to upgrade if (isset($keycolumns['permit'])) { qa_db_upgrade_progress('Skipping upgrading userfields table since it was already upgraded by another Q2A site sharing it.'); } else { qa_db_upgrade_query('ALTER TABLE ^userfields ADD COLUMN permit ' . $definitions['userfields']['permit'] . ' AFTER flags'); qa_db_upgrade_query($locktablesquery); } } break; case 52: if (!QA_FINAL_EXTERNAL_USERS) { $keyindexes = qa_array_to_keys(qa_db_read_all_assoc(qa_db_query_sub('SHOW INDEX FROM ^users'), null, 'Key_name')); if (isset($keyindexes['created'])) { qa_db_upgrade_progress('Skipping upgrading users table since it was already upgraded by another Q2A site sharing it.'); } else { qa_db_upgrade_query('ALTER TABLE ^users ADD KEY created (created, level, flags)'); qa_db_upgrade_query($locktablesquery); } } break; case 53: qa_db_upgrade_query('ALTER TABLE ^blobs CHANGE COLUMN content content ' . $definitions['blobs']['content']); qa_db_upgrade_query($locktablesquery); break; case 54: qa_db_upgrade_query('UNLOCK TABLES'); qa_db_upgrade_query('SET FOREIGN_KEY_CHECKS=0'); // in case InnoDB not available qa_db_upgrade_query(qa_db_create_table_sql('userlevels', array('userid' => $definitions['userlevels']['userid'], 'entitytype' => $definitions['userlevels']['entitytype'], 'entityid' => $definitions['userlevels']['entityid'], 'level' => $definitions['userlevels']['level'], 'UNIQUE userid (userid, entitytype, entityid)', 'KEY entitytype (entitytype, entityid)', QA_FINAL_EXTERNAL_USERS ? null : 'CONSTRAINT ^userlevels_ibfk_1 FOREIGN KEY (userid) REFERENCES ^users(userid) ON DELETE CASCADE'))); $locktablesquery .= ', ^userlevels WRITE'; qa_db_upgrade_query($locktablesquery); break; // Up to here: Version 1.6 beta 1 // Up to here: Version 1.6 beta 1 case 55: if (!QA_FINAL_EXTERNAL_USERS) { $keycolumns = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^users'))); // might be using messages table shared with another installation, so check if we need to upgrade if (isset($keycolumns['wallposts'])) { qa_db_upgrade_progress('Skipping upgrading users table since it was already upgraded by another Q2A site sharing it.'); } else { qa_db_upgrade_query('ALTER TABLE ^users ADD COLUMN wallposts ' . $definitions['users']['wallposts'] . ' AFTER flags'); qa_db_upgrade_query($locktablesquery); } } break; // Up to here: Version 1.6 beta 2 // Up to here: Version 1.6 beta 2 case 56: qa_db_upgrade_query('ALTER TABLE ^pages DROP INDEX tags, ADD KEY tags (tags)'); qa_db_upgrade_query($locktablesquery); break; // Up to here: Version 1.6 (release) // Up to here: Version 1.6 (release) case 57: if (!QA_FINAL_EXTERNAL_USERS) { // might be using messages table shared with another installation, so check if we need to upgrade $keycolumns = qa_array_to_keys(qa_db_read_all_values(qa_db_query_sub('SHOW COLUMNS FROM ^messages'))); if (isset($keycolumns['fromhidden'])) { qa_db_upgrade_progress('Skipping upgrading messages table since it was already upgraded by another Q2A site sharing it.'); } else { qa_db_upgrade_query('ALTER TABLE ^messages ADD COLUMN fromhidden ' . $definitions['messages']['fromhidden'] . ' AFTER touserid'); qa_db_upgrade_query('ALTER TABLE ^messages ADD COLUMN tohidden ' . $definitions['messages']['tohidden'] . ' AFTER fromhidden'); qa_db_upgrade_query('ALTER TABLE ^messages ADD KEY fromhidden (fromhidden), ADD KEY tohidden (tohidden)'); qa_db_upgrade_query($locktablesquery); } } break; case 58: // Note: need to use full table names here as aliases trigger error "Table 'x' was not locked with LOCK TABLES" qa_db_upgrade_query('DELETE FROM ^userfavorites WHERE entitytype="U" AND userid=entityid'); qa_db_upgrade_query('DELETE ^uservotes FROM ^uservotes JOIN ^posts ON ^uservotes.postid=^posts.postid AND ^uservotes.userid=^posts.userid'); qa_db_upgrade_query($locktablesquery); $keyrecalc['dorecountposts'] = true; $keyrecalc['dorecalcpoints'] = true; break; // Up to here: Verison 1.7 // Up to here: Verison 1.7 case 59: // Upgrade from alpha version removed break; // Up to here: Verison 1.7.1 } qa_db_set_db_version($newversion); if (qa_db_get_db_version() != $newversion) { qa_fatal_error('Could not increment database version'); } } qa_db_upgrade_query('UNLOCK TABLES'); // Perform any necessary recalculations, as determined by upgrade steps foreach ($keyrecalc as $state => $dummy) { while ($state) { set_time_limit(60); $stoptime = time() + 2; while (qa_recalc_perform_step($state) && time() < $stoptime) { } qa_db_upgrade_progress(qa_recalc_get_message($state)); } } }
function qa_load_theme_class($theme, $template, $content, $request) { global $qa_root_url_relative, $qa_layers; // First load the default class require_once QA_INCLUDE_DIR . 'qa-theme-base.php'; $classname = 'qa_html_theme_base'; // Then load the selected theme if valid, otherwise load the default theme if (!file_exists(QA_THEME_DIR . $theme . '/qa-styles.css')) { $theme = 'Default'; } $themeroothtml = qa_html($qa_root_url_relative . 'qa-theme/' . $theme . '/'); if (file_exists(QA_THEME_DIR . $theme . '/qa-theme.php')) { require_once QA_THEME_DIR . $theme . '/qa-theme.php'; if (class_exists('qa_html_theme')) { $classname = 'qa_html_theme'; } } // Then load any theme layers using some class-munging magic (substitute class names) $layerindex = 0; foreach ($qa_layers as $layer) { $layerphp = trim(@file_get_contents($layer['directory'] . $layer['include'])); if (strlen($layerphp)) { $newclassname = 'qa_html_theme_layer_' . ++$layerindex; if (preg_match('/\\s+class\\s+qa_html_theme_layer\\s+extends\\s+qa_html_theme_base\\s+/im', $layerphp) != 1) { qa_fatal_error('Class for layer must be declared as "class qa_html_theme_layer extends qa_html_theme_base" in ' . $layer['directory'] . $layer['include']); } $searchwordreplace = array('qa_html_theme_layer' => $newclassname, 'qa_html_theme_base' => $classname, 'QA_HTML_THEME_LAYER_DIRECTORY' => "'" . $layer['directory'] . "'", 'QA_HTML_THEME_LAYER_URLTOROOT' => "'" . $qa_root_url_relative . $layer['urltoroot'] . "'"); foreach ($searchwordreplace as $searchword => $replace) { if (preg_match_all('/\\W(' . preg_quote($searchword, '/') . ')\\W/im', $layerphp, $matches, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE)) { $searchmatches = array_reverse($matches[1]); // don't use preg_replace due to complication of escaping replacement phrase foreach ($searchmatches as $searchmatch) { $layerphp = substr_replace($layerphp, $replace, $searchmatch[1], strlen($searchmatch[0])); } } } // echo '<PRE STYLE="text-align:left;">'.htmlspecialchars($layerphp).'</PRE>'; // to debug munged code eval('?' . '>' . $layerphp); $classname = $newclassname; } } // Finally, instantiate the object $themeclass = new $classname($template, $content, $themeroothtml, $request); return $themeclass; }