Commit 42a56c92 by Gideon Greenspan

1.6-beta-1

parent 2c67b77c
1.5.4
\ No newline at end of file
1.6-beta-1
\ No newline at end of file
......@@ -69,6 +69,19 @@
*/
/*
If you wish, you can define QA_BLOBS_DIRECTORY to store BLOBs (binary large objects) such
as avatars and uploaded files on disk, rather than in the database. If so this directory
must be writable by the web server process - on Unix/Linux use chown/chmod as appropriate.
Note than if multiple Q2A sites are using QA_MYSQL_USERS_PREFIX to share users, they must
also have the same value for QA_BLOBS_DIRECTORY.
If there are already some BLOBs stored in the database from previous uploads, click the
'Move BLOBs to disk' button in the 'Stats' section of the admin panel to move them to disk.
define('QA_BLOBS_DIRECTORY', '/path/to/writable_blobs_directory/');
*/
/*
If you wish, you can define QA_COOKIE_DOMAIN so that any cookies created by Q2A are assigned
to a specific domain name, instead of the full domain name of the request by default. This is
useful if you're running multiple Q2A sites on subdomains with a shared user base.
......
......@@ -32,7 +32,7 @@ window.onbeforeunload=function(event)
event.returnValue=message;
return message;
}
}
};
function qa_recalc_click(state, elem, value, noteid)
{
......@@ -58,7 +58,7 @@ function qa_recalc_click(state, elem, value, noteid)
function qa_recalc_update(elem, state, noteid)
{
if (state)
qa_ajax_post('recalc', {state:state},
qa_ajax_post('recalc', {state:state, code:elem.form.elements.code.value},
function(lines) {
if (lines[0]=='1') {
if (lines[2])
......@@ -114,16 +114,18 @@ function qa_admin_click(target)
{
var p=target.name.split('_');
var params={postid:p[1], action:p[2]};
var params={entityid:p[1], action:p[2]};
params.code=target.form.elements.code.value;
qa_ajax_post('click_admin', params,
function (lines) {
if (lines[0]=='1') {
qa_conceal(document.getElementById('p'+p[1]), 'q_item');
} else {
if (lines[0]=='1')
qa_conceal(document.getElementById('p'+p[1]), 'admin');
else if (lines[0]=='0') {
alert(lines[1]);
qa_hide_waiting(target);
} else
qa_ajax_error();
}
}
);
......
......@@ -51,8 +51,6 @@ function qa_set_outer_html(elem, type, html)
function qa_show_waiting_after(elem, inside)
{
if (elem && !elem.qa_waiting_shown) {
elem.qa_waiting_shown=true;
var w=document.getElementById('qa-waiting-template');
if (w) {
......@@ -63,18 +61,31 @@ function qa_show_waiting_after(elem, inside)
elem.insertBefore(c, null);
else
elem.parentNode.insertBefore(c, elem.nextSibling);
elem.qa_waiting_shown=c;
}
}
}
function qa_hide_waiting(elem)
{
var c=elem.qa_waiting_shown;
if (c) {
c.parentNode.removeChild(c);
elem.qa_waiting_shown=null;
}
}
function qa_vote_click(elem)
{
var ens=elem.name.split('_');
var postid=ens[1];
var vote=parseInt(ens[2]);
var code=elem.form.elements.code.value;
var anchor=ens[3];
qa_ajax_post('vote', {postid:postid, vote:vote},
qa_ajax_post('vote', {postid:postid, vote:vote, code:code},
function(lines) {
if (lines[0]=='1') {
qa_set_inner_html(document.getElementById('voting_'+postid), 'voting', lines.slice(1).join("\n"));
......@@ -105,11 +116,14 @@ function qa_vote_click(elem)
function qa_notice_click(elem)
{
var ens=elem.name.split('_');
var code=elem.form.elements.code.value;
qa_ajax_post('notice', {noticeid:ens[1]},
qa_ajax_post('notice', {noticeid:ens[1], code:code},
function(lines) {
if (lines[0]=='1')
qa_conceal(document.getElementById('notice_'+ens[1]), 'notice');
else if (lines[0]=='0')
alert(lines[1]);
else
qa_ajax_error();
}
......@@ -121,12 +135,16 @@ function qa_notice_click(elem)
function qa_favorite_click(elem)
{
var ens=elem.name.split('_');
var code=elem.form.elements.code.value;
qa_ajax_post('favorite', {entitytype:ens[1], entityid:ens[2], favorite:parseInt(ens[3])},
qa_ajax_post('favorite', {entitytype:ens[1], entityid:ens[2], favorite:parseInt(ens[3]), code:code},
function (lines) {
if (lines[0]=='1')
qa_set_inner_html(document.getElementById('favoriting'), 'favoriting', lines.slice(1).join("\n"));
else
else if (lines[0]=='0') {
alert(lines[1]);
qa_hide_waiting(elem);
} else
qa_ajax_error();
}
);
......
......@@ -86,7 +86,9 @@ function qa_submit_answer(questionid, elem)
b.style.display='none';
}
qa_set_inner_html(document.getElementById('a_list_title'), 'a_list_title', lines[2]);
var t=document.getElementById('a_list_title');
qa_set_inner_html(t, 'a_list_title', lines[2]);
qa_reveal(t, 'a_list_title');
var e=document.createElement('DIV');
e.innerHTML=lines.slice(3).join("\n");
......@@ -104,7 +106,6 @@ function qa_submit_answer(questionid, elem)
qa_conceal(a, 'form');
} else if (lines[0]=='0') {
// document.forms['q_page_form'].elements['a_doadd2'].value=1;
document.forms['a_form'].submit();
} else {
......@@ -146,7 +147,6 @@ function qa_submit_comment(questionid, parentid, elem)
qa_conceal(a, 'form');
} else if (lines[0]=='0') {
// document.forms['q_page_form'].elements['c'+parentid+'_doadd2'].value=1;
document.forms['c_form_'+parentid].submit();
} else {
......@@ -167,7 +167,7 @@ function qa_answer_click(answerid, questionid, target)
params.answerid=answerid;
params.questionid=questionid;
params.code=target.form.elements.code.value;
params[target.name]=target.value;
qa_ajax_post('click_a', params,
......@@ -184,8 +184,8 @@ function qa_answer_click(answerid, questionid, target)
qa_conceal(l, 'answer');
} else {
document.forms['q_page_form'].elements['qa_click'].value=target.name;
document.forms['q_page_form'].submit();
target.form.elements.qa_click.value=target.name;
target.form.submit();
}
}
);
......@@ -202,7 +202,7 @@ function qa_comment_click(commentid, questionid, parentid, target)
params.commentid=commentid;
params.questionid=questionid;
params.parentid=parentid;
params.code=target.form.elements.code.value;
params[target.name]=target.value;
qa_ajax_post('click_c', params,
......@@ -217,8 +217,8 @@ function qa_comment_click(commentid, questionid, parentid, target)
qa_conceal(l, 'comment');
} else {
document.forms['q_page_form'].elements['qa_click'].value=target.name;
document.forms['q_page_form'].submit();
target.form.elements.qa_click.value=target.name;
target.form.submit();
}
}
);
......@@ -228,10 +228,11 @@ function qa_comment_click(commentid, questionid, parentid, target)
return false;
}
function qa_show_comments(parentid, elem)
function qa_show_comments(questionid, parentid, elem)
{
var params={};
params.c_questionid=questionid;
params.c_parentid=parentid;
qa_ajax_post('show_cs', params,
......
/*
Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/
File: qa-content/qa-user.js
Version: See define()s at top of qa-include/qa-base.php
Description: Javascript to handle question page actions
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
More about this license: http://www.question2answer.org/license.php
*/
function qa_submit_wall_post(elem)
{
var params={};
params.message=document.forms.wallpost.message.value;
params.handle=document.forms.wallpost.handle.value;
params.code=document.forms.wallpost.code.value;
qa_ajax_post('wallpost', params,
function(lines) {
if (lines[0]=='1') {
var l=document.getElementById('wallmessages');
l.innerHTML=lines.slice(2).join("\n");
var c=document.getElementById(lines[1]); // id of new message
if (c) {
c.style.display='none';
qa_reveal(c, 'wallpost');
}
document.forms.wallpost.message.value='';
qa_hide_waiting(elem);
} else if (lines[0]=='0') {
document.forms.wallpost.qa_click.value=elem.name;
document.forms.wallpost.submit();
} else {
qa_ajax_error();
}
}
);
qa_show_waiting_after(elem, false);
return false;
}
function qa_wall_post_click(messageid, target)
{
var params={};
params.messageid=messageid;
params.handle=document.forms.wallpost.handle.value;
params.code=document.forms.wallpost.code.value;
params[target.name]=target.value;
qa_ajax_post('click_wall', params,
function (lines) {
if (lines[0]=='1') {
var l=document.getElementById('m'+messageid);
var h=lines.slice(1).join("\n");
if (h.length)
qa_set_outer_html(l, 'wallpost', h)
else
qa_conceal(l, 'wallpost');
} else {
document.forms.wallpost.qa_click.value=target.name;
document.forms.wallpost.submit();
}
}
);
qa_show_waiting_after(target, false);
return false;
}
\ No newline at end of file
......@@ -176,6 +176,7 @@
* userid: a user id appropriate for your response to qa_get_mysql_user_column_type()
* publicusername: a user description you are willing to show publicly, e.g. the username
* email: the logged in user's email address
* passsalt: (optional) password salt specific to this user, used for form security codes
* level: one of the QA_USER_LEVEL_* values below to denote the user's privileges:
QA_USER_LEVEL_BASIC, QA_USER_LEVEL_EDITOR, QA_USER_LEVEL_ADMIN, QA_USER_LEVEL_SUPER
......
......@@ -26,12 +26,23 @@
require_once QA_INCLUDE_DIR.'qa-app-users.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php';
require_once QA_INCLUDE_DIR.'qa-db-selects.php';
// First check whether the person has permission to do this
// Load relevant information about this question
$questionid=qa_post_text('a_questionid');
$userid=qa_get_logged_in_userid();
list($question, $childposts)=qa_db_select_with_pending(
qa_db_full_post_selectspec($userid, $questionid),
qa_db_full_child_posts_selectspec($userid, $questionid)
);
if (!qa_user_permit_error('permit_post_a', QA_LIMIT_ANSWERS)) {
require_once QA_INCLUDE_DIR.'qa-db-selects.php';
// Check if the question exists, is not closed, and whether the user has permission to do this
if ((@$question['basetype']=='Q') && (!isset($question['closedbyid'])) && !qa_user_post_permit_error('permit_post_a', $question, QA_LIMIT_ANSWERS)) {
require_once QA_INCLUDE_DIR.'qa-app-captcha.php';
require_once QA_INCLUDE_DIR.'qa-app-format.php';
require_once QA_INCLUDE_DIR.'qa-app-post-create.php';
......@@ -40,65 +51,49 @@
require_once QA_INCLUDE_DIR.'qa-page-question-submit.php';
// Load relevant information about this question and check it exists
// Try to create the new answer
$usecaptcha=qa_user_use_captcha();
$questionid=qa_post_text('a_questionid');
$userid=qa_get_logged_in_userid();
list($question, $childposts)=qa_db_select_with_pending(
qa_db_full_post_selectspec($userid, $questionid),
qa_db_full_child_posts_selectspec($userid, $questionid)
);
$usecaptcha=qa_user_use_captcha(qa_user_level_for_post($question));
$answers=qa_page_q_load_as($question, $childposts);
$answerid=qa_page_q_add_a_submit($question, $answers, $usecaptcha, $in, $errors);
if ((@$question['basetype']=='Q') && !isset($question['closedbyid'])) {
$answers=qa_page_q_load_as($question, $childposts);
// If successful, page content will be updated via Ajax
if (isset($answerid)) {
$answer=qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $answerid));
// Try to create the new answer
$answerid=qa_page_q_add_a_submit($question, $answers, $usecaptcha, $in, $errors);
$question=$question+qa_page_q_post_rules($question, null, null, $childposts); // array union
$answer=$answer+qa_page_q_post_rules($answer, $question, $answers, null);
$countanswers=$question['acount']+1;
if (isset($answerid)) {
// If successful, page content will be updated via Ajax
$usershtml=qa_userids_handles_html(array($answer), true);
$a_view=qa_page_q_answer_view($question, $answer, false, $usershtml, false);
$themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-answer', null, null);
echo "QA_AJAX_RESPONSE\n1\n";
$answer=qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $answerid));
$question=$question+qa_page_q_post_rules($question, null, null, $childposts); // array union
$answer=$answer+qa_page_q_post_rules($answer, $question, $answers, null);
$usershtml=qa_userids_handles_html(array($answer), true);
$a_view=qa_page_q_answer_view($question, $answer, false, $usershtml, false);
$themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-answer', null, null);
echo "QA_AJAX_RESPONSE\n1\n";
// Send back whether the 'answer' button should still be visible
echo (int)qa_opt('allow_multi_answers')."\n";
// Send back whether the 'answer' button should still be visible
echo (int)qa_opt('allow_multi_answers')."\n";
// Send back the count of answers
$countanswers=$question['acount']+1;
// Send back the count of answers
if ($countanswers==1)
echo qa_lang_html('question/1_answer_title')."\n";
else
echo qa_lang_html_sub('question/x_answers_title', $countanswers)."\n";
if ($countanswers==1)
echo qa_lang_html('question/1_answer_title')."\n";
else
echo qa_lang_html_sub('question/x_answers_title', $countanswers)."\n";
// Send back the HTML
// Send back the HTML
$themeclass->a_list_item($a_view);
$themeclass->a_list_item($a_view);
return;
}
return;
}
}
......
......@@ -26,15 +26,18 @@
require_once QA_INCLUDE_DIR.'qa-app-admin.php';
require_once QA_INCLUDE_DIR.'qa-app-users.php';
require_once QA_INCLUDE_DIR.'qa-app-cookies.php';
$postid=qa_post_text('postid');
$entityid=qa_post_text('entityid');
$action=qa_post_text('action');
if (qa_admin_single_click($postid, $action)) // permission check happens in here
if (!qa_check_form_security_code('admin/click', qa_post_text('code')))
echo "QA_AJAX_RESPONSE\n0\n".qa_lang('misc/form_security_reload');
elseif (qa_admin_single_click($entityid, $action)) // permission check happens in here
echo "QA_AJAX_RESPONSE\n1\n";
else
echo "QA_AJAX_RESPONSE\n0\n";
echo "QA_AJAX_RESPONSE\n0\n".qa_lang('main/general_error');
/*
......
......@@ -39,7 +39,7 @@
$userid=qa_get_logged_in_userid();
@list($answer, $question, $qchildposts, $achildposts)=qa_db_select_with_pending(
list($answer, $question, $qchildposts, $achildposts)=qa_db_select_with_pending(
qa_db_full_post_selectspec($userid, $answerid),
qa_db_full_post_selectspec($userid, $questionid),
qa_db_full_child_posts_selectspec($userid, $questionid),
......@@ -94,7 +94,7 @@
$a_view=qa_page_q_answer_view($question, $answer, ($answer['postid']==$question['selchildid']) && ($answer['type']=='A'),
$usershtml, false);
$a_view['c_list']=qa_page_q_comment_follow_list($answer, $achildposts, false, $usershtml, false, null);
$a_view['c_list']=qa_page_q_comment_follow_list($question, $answer, $achildposts, false, $usershtml, false, null);
$themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-answer', null, null);
......
......@@ -40,7 +40,7 @@
$userid=qa_get_logged_in_userid();
@list($comment, $question, $parent, $children)=qa_db_select_with_pending(
list($comment, $question, $parent, $children)=qa_db_select_with_pending(
qa_db_full_post_selectspec($userid, $commentid),
qa_db_full_post_selectspec($userid, $questionid),
qa_db_full_post_selectspec($userid, $parentid),
......@@ -75,7 +75,7 @@
$usershtml=qa_userids_handles_html(array($comment), true);
$c_view=qa_page_q_comment_view($parent, $comment, $usershtml, false);
$c_view=qa_page_q_comment_view($question, $parent, $comment, $usershtml, false);
$themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-comment', null, null);
......
<?php
/*
Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/
File: qa-include/qa-ajax-click-wall.php
Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax single clicks on wall posts
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
More about this license: http://www.question2answer.org/license.php
*/
require_once QA_INCLUDE_DIR.'qa-app-messages.php';
require_once QA_INCLUDE_DIR.'qa-app-users.php';
require_once QA_INCLUDE_DIR.'qa-app-cookies.php';
require_once QA_INCLUDE_DIR.'qa-db-selects.php';
$tohandle=qa_post_text('handle');
$usermessages=qa_db_select_with_pending(qa_db_recent_messages_selectspec(null, null, $tohandle, false));
$loginuserid=qa_get_logged_in_userid();
$usermessages=qa_wall_posts_add_rules($usermessages, $loginuserid);
foreach ($usermessages as $message)
if (qa_clicked('m'.$message['messageid'].'_dodelete') && $message['deleteable'])
if (qa_check_form_security_code('wall-'.$tohandle, qa_post_text('code'))) {
qa_wall_delete_post($loginuserid, qa_get_logged_in_handle(), qa_cookie_get(), $message);
echo "QA_AJAX_RESPONSE\n1\n";
return;
}
echo "QA_AJAX_RESPONSE\n0\n";
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
......@@ -26,12 +26,29 @@
require_once QA_INCLUDE_DIR.'qa-app-users.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php';
require_once QA_INCLUDE_DIR.'qa-db-selects.php';
// First check whether the person has permission to do this
// Load relevant information about this question and the comment parent
if (!qa_user_permit_error('permit_post_c', QA_LIMIT_COMMENTS)) {
require_once QA_INCLUDE_DIR.'qa-db-selects.php';
$questionid=qa_post_text('c_questionid');
$parentid=qa_post_text('c_parentid');
$userid=qa_get_logged_in_userid();
list($question, $parent, $children)=qa_db_select_with_pending(
qa_db_full_post_selectspec($userid, $questionid),
qa_db_full_post_selectspec($userid, $parentid),
qa_db_full_child_posts_selectspec($userid, $parentid)
);
// Check if the question and parent exist, and whether the user has permission to do this
if (
(@$question['basetype']=='Q') &&
((@$parent['basetype']=='Q') || (@$parent['basetype']=='A')) &&
!qa_user_post_permit_error('permit_post_c', $parent, QA_LIMIT_COMMENTS))
{
require_once QA_INCLUDE_DIR.'qa-app-captcha.php';
require_once QA_INCLUDE_DIR.'qa-app-format.php';
require_once QA_INCLUDE_DIR.'qa-app-post-create.php';
......@@ -41,66 +58,44 @@
require_once QA_INCLUDE_DIR.'qa-util-sort.php';
// Load relevant information about this question and check it exists
// Try to create the new comment
$usecaptcha=qa_user_use_captcha();
$questionid=qa_post_text('c_questionid');
$parentid=qa_post_text('c_parentid');
$userid=qa_get_logged_in_userid();
@list($question, $parent, $children)=qa_db_select_with_pending(
qa_db_full_post_selectspec($userid, $questionid),
qa_db_full_post_selectspec($userid, $parentid),
qa_db_full_child_posts_selectspec($userid, $parentid)
);
if (
(@$question['basetype']=='Q') &&
((@$parent['basetype']=='Q') || (@$parent['basetype']=='A'))
) {
$usecaptcha=qa_user_use_captcha(qa_user_level_for_post($question));
$commentid=qa_page_q_add_c_submit($question, $parent, $children, $usecaptcha, $in, $errors);
// Try to create the new comment
$commentid=qa_page_q_add_c_submit($question, $parent, $children, $usecaptcha, $in, $errors);
// If successful, page content will be updated via Ajax
if (isset($commentid)) {
$children=qa_db_select_with_pending(qa_db_full_child_posts_selectspec($userid, $parentid));
if (isset($commentid)) {
// If successful, page content will be updated via Ajax
$children=qa_db_select_with_pending(qa_db_full_child_posts_selectspec($userid, $parentid));
$parent=$parent+qa_page_q_post_rules($parent, ($questionid==$parentid) ? null : $question, null, $children);
// in theory we should retrieve the parent's siblings for the above, but they're not going to be relevant
foreach ($children as $key => $child)
$children[$key]=$child+qa_page_q_post_rules($child, $parent, $children, null);
$usershtml=qa_userids_handles_html($children, true);
qa_sort_by($children, 'created');
$c_list=qa_page_q_comment_follow_list($parent, $children, true, $usershtml, false, null);
$themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-comments', null, null);
echo "QA_AJAX_RESPONSE\n1\n";
// Send back the ID of the new comment
$parent=$parent+qa_page_q_post_rules($parent, ($questionid==$parentid) ? null : $question, null, $children);
// in theory we should retrieve the parent's siblings for the above, but they're not going to be relevant
foreach ($children as $key => $child)
$children[$key]=$child+qa_page_q_post_rules($child, $parent, $children, null);
$usershtml=qa_userids_handles_html($children, true);
qa_sort_by($children, 'created');
$c_list=qa_page_q_comment_follow_list($question, $parent, $children, true, $usershtml, false, null);
$themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-comments', null, null);
echo "QA_AJAX_RESPONSE\n1\n";
// Send back the ID of the new comment
echo qa_anchor('C', $commentid)."\n";
echo qa_anchor('C', $commentid)."\n";
// Send back the HTML
// Send back the HTML
foreach ($c_list['cs'] as $c_item)
$themeclass->c_list_item($c_item);
$themeclass->c_list_items($c_list['cs']);
return;
}
return;
}
}
......
......@@ -36,7 +36,10 @@
$userid=qa_get_logged_in_userid();
if (isset($userid)) {
if (!qa_check_form_security_code('favorite-'.$entitytype.'-'.$entityid, qa_post_text('code')))
echo "QA_AJAX_RESPONSE\n0\n".qa_lang('misc/form_security_reload');
elseif (isset($userid)) {
$cookieid=qa_cookie_get();
qa_user_favorite_set($userid, qa_get_logged_in_handle(), $cookieid, $entitytype, $entityid, $setfavorite);
......
......@@ -31,20 +31,25 @@
$noticeid=qa_post_text('noticeid');
if ($noticeid=='visitor')
setcookie('qa_noticed', 1, time()+86400*3650, '/', QA_COOKIE_DOMAIN);
if (!qa_check_form_security_code('notice-'.$noticeid, qa_post_text('code')))
echo "QA_AJAX_RESPONSE\n0\n".qa_lang('misc/form_security_reload');
else {
$userid=qa_get_logged_in_userid();
if ($noticeid=='visitor')
setcookie('qa_noticed', 1, time()+86400*3650, '/', QA_COOKIE_DOMAIN);
if ($noticeid=='welcome')
qa_db_user_set_flag($userid, QA_USER_FLAGS_WELCOME_NOTICE, false);
else
qa_db_usernotice_delete($userid, $noticeid);
}
else {
$userid=qa_get_logged_in_userid();
if ($noticeid=='welcome')
qa_db_user_set_flag($userid, QA_USER_FLAGS_WELCOME_NOTICE, false);
else
qa_db_usernotice_delete($userid, $noticeid);
}
echo "QA_AJAX_RESPONSE\n1";
echo "QA_AJAX_RESPONSE\n1";
}
/*
......
......@@ -29,13 +29,20 @@
if (qa_get_logged_in_level()>=QA_USER_LEVEL_ADMIN) {
$state=qa_post_text('state');
$stoptime=time()+3;
while ( qa_recalc_perform_step($state) && (time()<$stoptime) )
;
if (!qa_check_form_security_code('admin/recalc', qa_post_text('code'))) {
$state='';
$message=qa_lang('misc/form_security_reload');
} else {
$state=qa_post_text('state');
$stoptime=time()+3;
$message=qa_recalc_get_message($state);
while ( qa_recalc_perform_step($state) && (time()<$stoptime) )
;
$message=qa_recalc_get_message($state);
}
} else {
$state='';
......
......@@ -34,10 +34,12 @@
// Load relevant information about this question and check it exists
$questionid=qa_post_text('c_questionid');
$parentid=qa_post_text('c_parentid');
$userid=qa_get_logged_in_userid();
list($parent, $children)=qa_db_select_with_pending(
list($question, $parent, $children)=qa_db_select_with_pending(
qa_db_full_post_selectspec($userid, $questionid),
qa_db_full_post_selectspec($userid, $parentid),
qa_db_full_child_posts_selectspec($userid, $parentid)
);
......@@ -53,7 +55,7 @@
qa_sort_by($children, 'created');
$c_list=qa_page_q_comment_follow_list($parent, $children, true, $usershtml, false, null);
$c_list=qa_page_q_comment_follow_list($question, $parent, $children, true, $usershtml, false, null);
$themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-comments', null, null);
......@@ -62,8 +64,7 @@
// Send back the HTML
foreach ($c_list['cs'] as $c_item)
$themeclass->c_list_item($c_item);
$themeclass->c_list_items($c_list['cs']);
return;
}
......
......@@ -34,13 +34,18 @@
$postid=qa_post_text('postid');
$vote=qa_post_text('vote');
$code=qa_post_text('code');
$userid=qa_get_logged_in_userid();
$cookieid=qa_cookie_get();
$post=qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $postid));
$voteerror=qa_vote_error_html($post, $vote, $userid, qa_request());
if (!qa_check_form_security_code('vote', $code))
$voteerror=qa_lang_html('misc/form_security_reload');
else {
$post=qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $postid));
$voteerror=qa_vote_error_html($post, $vote, $userid, qa_request());
}
if ($voteerror===false) {
qa_vote_set($post, $userid, qa_get_logged_in_handle(), $cookieid, $vote);
......@@ -48,7 +53,7 @@
$post=qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $postid));
$fields=qa_post_html_fields($post, $userid, $cookieid, array(), null, array(
'voteview' => qa_get_vote_view($post['basetype'], true), // behave as if on question page since the vote succeeded
'voteview' => qa_get_vote_view($post, true), // behave as if on question page since the vote succeeded
));
$themeclass=qa_load_theme_class(qa_get_site_theme(), 'voting', null, null);
......
<?php
/*
Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/
File: qa-include/qa-ajax-wallpost.php
Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax wall post requests
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
More about this license: http://www.question2answer.org/license.php
*/
require_once QA_INCLUDE_DIR.'qa-app-messages.php';
require_once QA_INCLUDE_DIR.'qa-app-users.php';
require_once QA_INCLUDE_DIR.'qa-app-cookies.php';
require_once QA_INCLUDE_DIR.'qa-db-selects.php';
$message=qa_post_text('message');
$tohandle=qa_post_text('handle');
$touseraccount=qa_db_select_with_pending(qa_db_user_account_selectspec($tohandle, false));
$loginuserid=qa_get_logged_in_userid();
$errorhtml=qa_wall_error_html($loginuserid, $touseraccount);
if ($errorhtml || (!strlen($message)) || !qa_check_form_security_code('wall-'.$tohandle, qa_post_text('code')) )
echo "QA_AJAX_RESPONSE\n0"; // if there's an error, process in non-Ajax way
else {
$messageid=qa_wall_add_post($loginuserid, qa_get_logged_in_handle(), qa_cookie_get(),
$touseraccount['userid'], $touseraccount['handle'], $message, '');
$usermessages=qa_db_select_with_pending(qa_db_recent_messages_selectspec(null, null, $touseraccount['userid'], true));
$usermessages=qa_wall_posts_add_rules($usermessages, $loginuserid);
$themeclass=qa_load_theme_class(qa_get_site_theme(), 'wall', null, null);
echo "QA_AJAX_RESPONSE\n1\n";
echo 'm'.$messageid."\n"; // element in list to be revealed
foreach ($usermessages as $message)
$themeclass->message_item(qa_wall_post_view($message, $loginuserid));
}
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
......@@ -74,6 +74,8 @@
'click_c' => 'qa-ajax-click-comment.php',
'click_admin' => 'qa-ajax-click-admin.php',
'show_cs' => 'qa-ajax-show-comments.php',
'wallpost' => 'qa-ajax-wallpost.php',
'click_wall' => 'qa-ajax-click-wall.php',
);
$operation=qa_post_text('qa_operation');
......
......@@ -41,27 +41,109 @@
}
function qa_get_max_upload_size()
/*
Return the maximum size of file that can be uploaded, based on database and PHP limits
*/
function qa_get_blob_directory($blobid)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return rtrim(QA_BLOBS_DIRECTORY, '/').'/'.substr(str_pad($blobid, 20, '0', STR_PAD_LEFT), 0, 3);
}
function qa_get_blob_filename($blobid, $format)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return qa_get_blob_directory($blobid).'/'.$blobid.'.'.preg_replace('/[^A-Za-z0-9]/', '', $format);
}
function qa_create_blob($content, $format, $sourcefilename=null, $userid=null, $cookieid=null, $ip=null)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-db-blobs.php';
$blobid=qa_db_blob_create(defined('QA_BLOBS_DIRECTORY') ? null : $content, $format, $sourcefilename, $userid, $cookieid, $ip);
if (defined('QA_BLOBS_DIRECTORY'))
if (!qa_write_blob_file($blobid, $content, $format))
qa_db_blob_set_content($blobid, $content); // still write to database if writing to disk failed
return $blobid;
}
function qa_write_blob_file($blobid, $content, $format)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$written=false;
$directory=qa_get_blob_directory($blobid);
if (is_dir($directory) || mkdir($directory, fileperms(rtrim(QA_BLOBS_DIRECTORY, '/')) & 0777)) {
$filename=qa_get_blob_filename($blobid, $format);
$file=fopen($filename, 'xb');
if (is_resource($file)) {
if (fwrite($file, $content)>=strlen($content))
$written=true;
fclose($file);
if (!$written)
unlink($filename);
}
}
return $written;
}
function qa_read_blob($blobid)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$mindb=16777215; // from MEDIUMBLOB column type
require_once QA_INCLUDE_DIR.'qa-db-blobs.php';
$blob=qa_db_blob_read($blobid);
$minphp=trim(ini_get('upload_max_filesize'));
if (defined('QA_BLOBS_DIRECTORY') && !isset($blob['content']))
$blob['content']=qa_read_blob_file($blobid, $blob['format']);
return $blob;
}
function qa_read_blob_file($blobid, $format)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return file_get_contents(qa_get_blob_filename($blobid, $format));
}
function qa_delete_blob($blobid)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
switch (strtolower(substr($minphp, -1))) {
case 'g':
$minphp*=1024;
case 'm':
$minphp*=1024;
case 'k':
$minphp*=1024;
require_once QA_INCLUDE_DIR.'qa-db-blobs.php';
if (defined('QA_BLOBS_DIRECTORY')) {
$blob=qa_db_blob_read($blobid);
if (isset($blob) && !isset($blob['content']))
unlink(qa_get_blob_filename($blobid, $blob['format']));
}
return min($mindb, $minphp);
qa_db_blob_delete($blobid);
}
function qa_delete_blob_file($blobid, $format)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
unlink(qa_get_blob_filename($blobid, $format));
}
......
......@@ -41,6 +41,28 @@
}
function qa_captcha_reason_note($captchareason)
{
$notehtml=null;
switch ($captchareason) {
case 'login':
$notehtml=qa_insert_login_links(qa_lang_html('misc/captcha_login_fix'));
break;
case 'confirm':
$notehtml=qa_insert_login_links(qa_lang_html('misc/captcha_confirm_fix'));
break;
case 'approve':
$notehtml=qa_lang_html('misc/captcha_approve_fix');
break;
}
return $notehtml;
}
function qa_set_up_captcha_field(&$qa_content, &$fields, $errors, $note=null)
/*
Prepare $qa_content for showing a captcha, adding the element to $fields, given previous $errors, and a $note to display
......
......@@ -119,6 +119,8 @@
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
// @error_log(print_r($params, true));
require_once QA_INCLUDE_DIR.'qa-class.phpmailer.php';
$mailer=new PHPMailer();
......
......@@ -41,6 +41,15 @@
define('QA_LIMIT_MESSAGES', 'M');
function qa_user_limits_remaining($action)
{
$userlimits=qa_db_get_pending_result('userlimits', qa_db_user_limits_selectspec(qa_get_logged_in_userid()));
$iplimits=qa_db_get_pending_result('iplimits', qa_db_ip_limits_selectspec(qa_remote_ip_address()));
return qa_limits_calc_remaining($action, @$userlimits[$action], @$iplimits[$action]);
}
function qa_limits_remaining($userid, $action)
/*
Return how many more times user $userid and/or the requesting IP can perform $action this hour,
......@@ -49,56 +58,60 @@
{
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);
return qa_limits_calc_remaining($action, $dblimits['user'], $dblimits['ip']);
}
function qa_limits_calc_remaining($action, $userlimits, $iplimits)
{
switch ($action) {
case QA_LIMIT_QUESTIONS:
$userlimit=qa_opt('max_rate_user_qs');
$iplimit=qa_opt('max_rate_ip_qs');
$usermax=qa_opt('max_rate_user_qs');
$ipmax=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');
$usermax=qa_opt('max_rate_user_as');
$ipmax=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');
$usermax=qa_opt('max_rate_user_cs');
$ipmax=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');
$usermax=qa_opt('max_rate_user_votes');
$ipmax=qa_opt('max_rate_ip_votes');
break;
case QA_LIMIT_REGISTRATIONS:
$userlimit=1; // not really relevant
$iplimit=qa_opt('max_rate_ip_registers');
$usermax=1; // not really relevant
$ipmax=qa_opt('max_rate_ip_registers');
break;
case QA_LIMIT_LOGINS:
$userlimit=1; // not really relevant
$iplimit=qa_opt('max_rate_ip_logins');
$usermax=1; // not really relevant
$ipmax=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');
$usermax=qa_opt('max_rate_user_uploads');
$ipmax=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');
$usermax=qa_opt('max_rate_user_flags');
$ipmax=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');
$usermax=qa_opt('max_rate_user_messages');
$ipmax=qa_opt('max_rate_ip_messages');
break;
default:
......@@ -106,9 +119,11 @@
break;
}
$period=(int)(qa_opt('db_time')/3600);
return max(0, min(
$userlimit-((@$dblimits['user']['period']==$period) ? $dblimits['user']['count'] : 0),
$iplimit-((@$dblimits['ip']['period']==$period) ? $dblimits['ip']['count'] : 0)
$usermax-((@$userlimits['period']==$period) ? $userlimits['count'] : 0),
$ipmax-((@$iplimits['period']==$period) ? $iplimits['count'] : 0)
));
}
......
......@@ -122,7 +122,7 @@
qa_db_user_set($userid, 'emailcode', $emailcode);
}
$unsubscribeurl=qa_path('unsubscribe', array('c' => $emailcode, 'u' => $handle), qa_opt('site_url'));
$unsubscribeurl=qa_path_absolute('unsubscribe', array('c' => $emailcode, 'u' => $handle));
return qa_send_email(array(
'fromemail' => qa_opt('mailing_from_email'),
......
<?php
/*
Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/
File: qa-include/qa-app-messages.php
Version: See define()s at top of qa-include/qa-base.php
Description: Handling public/private messages
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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;
}
function qa_wall_error_html($fromuserid, $touseraccount)
{
require_once QA_INCLUDE_DIR.'qa-app-limits.php';
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
if ((!QA_FINAL_EXTERNAL_USERS) && qa_opt('allow_user_walls')) {
if ( ($touseraccount['flags'] & QA_USER_FLAGS_NO_WALL_POSTS) && !(isset($fromuserid) && ($fromuserid==$touseraccount['userid'])) )
return qa_lang_html('profile/post_wall_blocked');
else
switch (qa_user_permit_error('permit_post_wall', QA_LIMIT_MESSAGES)) {
case 'limit':
return qa_lang_html('profile/post_wall_limit');
break;
case 'login':
return qa_insert_login_links(qa_lang_html('profile/post_wall_must_login'), qa_request());
break;
case 'confirm':
return qa_insert_login_links(qa_lang_html('profile/post_wall_must_confirm'), qa_request());
break;
case 'approve':
return qa_lang_html('profile/post_wall_must_be_approved');
break;
case false:
return false;
break;
}
}
return qa_lang_html('users/no_permission');
}
function qa_wall_add_post($userid, $handle, $cookieid, $touserid, $tohandle, $content, $format)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-app-format.php';
require_once QA_INCLUDE_DIR.'qa-db-messages.php';
$messageid=qa_db_message_create($userid, $touserid, $content, $format, true);
qa_report_event('u_wall_post', $userid, $handle, $cookieid, array(
'userid' => $touserid,
'handle' => $tohandle,
'messageid' => $messageid,
'content' => $content,
'format' => $format,
'text' => qa_viewer_text($content, $format),
));
return $messageid;
}
function qa_wall_delete_post($userid, $handle, $cookieid, $message)
{
require_once QA_INCLUDE_DIR.'qa-db-messages.php';
qa_db_message_delete($message['messageid']);
qa_report_event('u_wall_delete', $userid, $handle, $cookieid, array(
'messageid' => $message['messageid'],
'oldmessage' => $message,
));
}
function qa_wall_posts_add_rules($usermessages, $userid)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$deleteable=isset($userid); // can delete all most recent messages...
foreach ($usermessages as $key => $message) {
if (($message['touserid']!=$userid) && ($message['fromuserid']!=$userid))
$deleteable=false; // ... until we come across one that doesn't involve me
$usermessages[$key]['deleteable']=$deleteable;
}
return $usermessages;
}
function qa_wall_post_view($message, $userid)
{
require_once QA_INCLUDE_DIR.'qa-app-format.php';
$options=qa_message_html_defaults();
$htmlfields=qa_message_html_fields($message, $userid, $options);
if ($message['deleteable'])
$htmlfields['form']=array(
'style' => 'light',
'buttons' => array(
'delete' => array(
'tags' => 'NAME="m'.qa_html($message['messageid']).'_dodelete" onClick="return qa_wall_post_click('.qa_js($message['messageid']).', this);"',
'label' => qa_lang_html('question/delete_button'),
'popup' => qa_lang_html('profile/delete_wall_post_popup'),
),
),
);
return $htmlfields;
}
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
......@@ -36,6 +36,8 @@
define('QA_PERMIT_CONFIRMED', 110);
define('QA_PERMIT_POINTS', 106);
define('QA_PERMIT_POINTS_CONFIRMED', 104);
define('QA_PERMIT_APPROVED', 103);
define('QA_PERMIT_APPROVED_POINTS', 102);
define('QA_PERMIT_EXPERTS', 100);
define('QA_PERMIT_EDITORS', 70);
define('QA_PERMIT_MODERATORS', 40);
......@@ -204,14 +206,17 @@
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$fixed_defaults=array(
'allow_anon_name' => 1,
'allow_change_usernames' => 1,
'allow_close_questions' => 1,
'allow_multi_answers' => 1,
'allow_private_messages' => 1,
'allow_user_walls' => 1,
'allow_self_answer' => 1,
'allow_view_q_bots' => 1,
'avatar_allow_gravatar' => 1,
'avatar_allow_upload' => 1,
'avatar_message_list_size' => 20,
'avatar_profile_size' => 200,
'avatar_q_list_size' => 0,
'avatar_q_page_a_size' => 40,
......@@ -282,6 +287,7 @@
'min_num_q_tags' => 0,
'moderate_notify_admin' => 1,
'moderate_points_limit' => 150,
'moderate_update_time' => 1,
'nav_ask' => 1,
'nav_qa_not_home' => 1,
'nav_questions' => 1,
......@@ -302,7 +308,6 @@
'page_size_tag_qs' => 20,
'page_size_tags' => 30,
'page_size_una_qs' => 20,
'page_size_user_posts' => 20,
'page_size_users' => 20,
'pages_prev_next' => 3,
'permit_anon_view_ips' => QA_PERMIT_EDITORS,
......@@ -311,11 +316,14 @@
'permit_edit_a' => QA_PERMIT_EXPERTS,
'permit_edit_c' => QA_PERMIT_EDITORS,
'permit_edit_q' => QA_PERMIT_EDITORS,
'permit_edit_silent' => QA_PERMIT_MODERATORS,
'permit_flag' => QA_PERMIT_CONFIRMED,
'permit_hide_show' => QA_PERMIT_EDITORS,
'permit_moderate' => QA_PERMIT_EXPERTS,
'permit_post_wall' => QA_PERMIT_CONFIRMED,
'permit_select_a' => QA_PERMIT_EXPERTS,
'permit_view_q_page' => QA_PERMIT_ALL,
'permit_view_voters_flaggers' => QA_PERMIT_ADMINS,
'permit_vote_a' => QA_PERMIT_USERS,
'permit_vote_down' => QA_PERMIT_USERS,
'permit_vote_q' => QA_PERMIT_USERS,
......@@ -472,6 +480,11 @@
case 'mailing_body':
$value="\n\n\n--\n".qa_opt('site_title')."\n".qa_opt('site_url');
break;
case 'form_security_salt':
require_once QA_INCLUDE_DIR.'qa-util-string.php';
$value=qa_random_alphanum(32);
break;
default: // call option_default method in any registered modules
$moduletypes=qa_list_module_types();
......@@ -525,8 +538,9 @@
'contentview' => $full,
'voteview' => qa_get_vote_view($basetype, $full),
'flagsview' => qa_opt('flagging_of_posts') && $full,
'favoritedview' => true,
'answersview' => $basetype=='Q',
'viewsview' => ($basetype=='Q') && qa_opt('do_count_q_views') && qa_opt('show_view_counts'),
'viewsview' => ($basetype=='Q') && qa_opt('do_count_q_views') && ($full ? qa_opt('show_view_count_q_page') : qa_opt('show_view_counts')),
'whatview' => true,
'whatlink' => qa_opt('show_a_c_links'),
'whenview' => qa_opt('show_when_created'),
......@@ -544,37 +558,87 @@
);
}
function qa_post_html_options($post, $defaults=null, $full=false)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
if (!isset($defaults))
$defaults=qa_post_html_defaults($post['basetype'], $full);
$defaults['voteview']=qa_get_vote_view($post, $full);
$defaults['ipview']=!qa_user_post_permit_error('permit_anon_view_ips', $post);
return $defaults;
}
function qa_message_html_defaults()
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return array(
'whenview' => qa_opt('show_when_created'),
'whoview' => true,
'avatarsize' => qa_opt('avatar_message_list_size'),
'blockwordspreg' => qa_get_block_words_preg(),
'showurllinks' => qa_opt('show_url_links'),
'linksnewwindow' => qa_opt('links_in_new_window'),
'fulldatedays' => qa_opt('show_full_date_days'),
);
}
function qa_get_vote_view($basetype, $full=false, $enabledif=true)
function qa_get_vote_view($postorbasetype, $full=false, $enabledif=true)
/*
Return $voteview parameter to pass to qa_post_html_fields() in qa-app-format.php for posts of $basetype (Q/A/C),
Return $voteview parameter to pass to qa_post_html_fields() in qa-app-format.php for the post in $postorbasetype
with buttons enabled if appropriate (based on whether $full post shown) unless $enabledif is false.
For compatibility $postorbasetype can also just be a basetype, i.e. 'Q', 'A' or 'C'
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
// The 'level' and 'approve' permission errors are taken care of by disabling the voting buttons.
// Others are reported to the user after they click, in qa_vote_error_html(...)
if (is_array($postorbasetype)) { // deal with dual-use parameter
$basetype=$postorbasetype['basetype'];
$post=$postorbasetype;
} else {
$basetype=$postorbasetype;
$post=null;
}
$disabledsuffix='';
if ($basetype=='Q') {
$view=qa_opt('voting_on_qs');
if (!($enabledif && ($full || !qa_opt('voting_on_q_page_only'))))
$disabledsuffix='-disabled-page';
elseif (qa_user_permit_error('permit_vote_q')=='level')
$disabledsuffix='-disabled-level';
elseif (qa_user_permit_error('permit_vote_down')=='level')
$disabledsuffix='-uponly-level';
} elseif ($basetype=='A') {
$view=qa_opt('voting_on_as');
if (($basetype=='Q') || ($basetype=='A')) {
$view=($basetype=='A') ? qa_opt('voting_on_as') : qa_opt('voting_on_qs');
if (!$enabledif)
if (!($enabledif && (($basetype=='A') || $full || !qa_opt('voting_on_q_page_only'))))
$disabledsuffix='-disabled-page';
elseif (qa_user_permit_error('permit_vote_a')=='level')
$disabledsuffix='-disabled-level';
elseif (qa_user_permit_error('permit_vote_down')=='level')
$disabledsuffix='-uponly-level';
else {
if ($basetype=='A')
$permiterror=isset($post) ? qa_user_post_permit_error('permit_vote_a', $post) : qa_user_permit_error('permit_vote_a');
else
$permiterror=isset($post) ? qa_user_post_permit_error('permit_vote_q', $post) : qa_user_permit_error('permit_vote_q');
if ($permiterror=='level')
$disabledsuffix='-disabled-level';
elseif ($permiterror=='approve')
$disabledsuffix='-disabled-approve';
else {
$permiterrordown=isset($post) ? qa_user_post_permit_error('permit_vote_down', $post) : qa_user_permit_error('permit_vote_down');
if ($permiterrordown=='level')
$disabledsuffix='-uponly-level';
elseif ($permiterrordown=='approve')
$disabledsuffix='-uponly-approve';
}
}
} else
$view=false;
......@@ -692,12 +756,17 @@
if (qa_opt('comment_on_qs') || qa_opt('comment_on_as'))
$permits[]='permit_edit_c';
$permits[]='permit_edit_silent';
if (qa_opt('allow_close_questions'))
$permits[]='permit_close_q';
array_push($permits, 'permit_select_a', 'permit_anon_view_ips');
if (qa_opt('voting_on_qs') || qa_opt('voting_on_as') || qa_opt('flagging_of_posts'))
$permits[]='permit_view_voters_flaggers';
if (qa_opt('flagging_of_posts'))
$permits[]='permit_flag';
......@@ -705,6 +774,9 @@
array_push($permits, 'permit_hide_show', 'permit_delete_hidden');
if (qa_opt('allow_user_walls'))
$permits[]='permit_post_wall';
return $permits;
}
......
......@@ -46,7 +46,7 @@
function qa_question_create($followanswer, $userid, $handle, $cookieid, $title, $content, $format, $text, $tagstring, $notify, $email,
$categoryid=null, $extravalue=null, $queued=false)
$categoryid=null, $extravalue=null, $queued=false, $name=null)
/*
Add a question (application level) - create record, update appropriate counts, index it, send notifications.
If question is follow-on from an answer, $followanswer should contain answer database record, otherwise null.
......@@ -56,7 +56,8 @@
require_once QA_INCLUDE_DIR.'qa-db-selects.php';
$postid=qa_db_post_create($queued ? 'Q_QUEUED' : 'Q', @$followanswer['postid'], $userid, isset($userid) ? null : $cookieid,
qa_remote_ip_address(), $title, $content, $format, $tagstring, qa_combine_notify_email($userid, $notify, $email), $categoryid);
qa_remote_ip_address(), $title, $content, $format, $tagstring, qa_combine_notify_email($userid, $notify, $email),
$categoryid, isset($userid) ? null : $name);
if (isset($extravalue)) {
require_once QA_INCLUDE_DIR.'qa-db-metas.php';
......@@ -66,14 +67,13 @@
qa_db_posts_calc_category_path($postid);
qa_db_hotness_update($postid);
if (!$queued) {
qa_db_category_path_qcount_update(qa_db_post_get_category_path($postid));
if ($queued) {
qa_db_queuedcount_update();
} else {
qa_post_index($postid, 'Q', $postid, @$followanswer['postid'], $title, $content, $format, $text, $tagstring, $categoryid);
qa_update_counts_for_q($postid);
qa_db_points_update_ifuser($userid, 'qposts');
qa_db_qcount_update();
qa_db_unaqcount_update();
qa_db_unselqcount_update();
qa_db_unupaqcount_update();
}
qa_report_event($queued ? 'q_queue' : 'q_post', $userid, $handle, $cookieid, array(
......@@ -87,6 +87,7 @@
'tags' => $tagstring,
'categoryid' => $categoryid,
'extra' => $extravalue,
'name' => $name,
'notify' => $notify,
'email' => $email,
));
......@@ -95,6 +96,18 @@
}
function qa_update_counts_for_q($postid)
{
if (isset($postid)) // post might no longer exist
qa_db_category_path_qcount_update(qa_db_post_get_category_path($postid));
qa_db_qcount_update();
qa_db_unaqcount_update();
qa_db_unselqcount_update();
qa_db_unupaqcount_update();
}
function qa_array_filter_by_keys($inarray, $keys)
/*
Return an array containing the elements of $inarray whose key is in $keys
......@@ -141,7 +154,7 @@
}
function qa_answer_create($userid, $handle, $cookieid, $content, $format, $text, $notify, $email, $question, $queued=false)
function qa_answer_create($userid, $handle, $cookieid, $content, $format, $text, $notify, $email, $question, $queued=false, $name=null)
/*
Add an answer (application level) - create record, update appropriate counts, index it, send notifications.
$question should contain database record for the question this is an answer to.
......@@ -149,19 +162,20 @@
*/
{
$postid=qa_db_post_create($queued ? 'A_QUEUED' : 'A', $question['postid'], $userid, isset($userid) ? null : $cookieid,
qa_remote_ip_address(), null, $content, $format, null, qa_combine_notify_email($userid, $notify, $email), $question['categoryid']);
qa_remote_ip_address(), null, $content, $format, null, qa_combine_notify_email($userid, $notify, $email),
$question['categoryid'], isset($userid) ? null : $name);
qa_db_posts_calc_category_path($postid);
if (!$queued) {
if ($queued) {
qa_db_queuedcount_update();
} else {
if ($question['type']=='Q') // don't index answer if parent question is hidden or queued
qa_post_index($postid, 'A', $question['postid'], $question['postid'], null, $content, $format, $text, null, $question['categoryid']);
qa_db_post_acount_update($question['postid']);
qa_db_hotness_update($question['postid']);
qa_update_q_counts_for_a($question['postid']);
qa_db_points_update_ifuser($userid, 'aposts');
qa_db_acount_update();
qa_db_unaqcount_update();
}
qa_report_event($queued ? 'a_queue' : 'a_post', $userid, $handle, $cookieid, array(
......@@ -172,15 +186,26 @@
'format' => $format,
'text' => $text,
'categoryid' => $question['categoryid'],
'name' => $name,
'notify' => $notify,
'email' => $email,
));
return $postid;
}
function qa_update_q_counts_for_a($questionid)
{
qa_db_post_acount_update($questionid);
qa_db_hotness_update($questionid);
qa_db_acount_update();
qa_db_unaqcount_update();
qa_db_unupaqcount_update();
}
function qa_comment_create($userid, $handle, $cookieid, $content, $format, $text, $notify, $email, $question, $parent, $commentsfollows, $queued=false)
function qa_comment_create($userid, $handle, $cookieid, $content, $format, $text, $notify, $email, $question, $parent, $commentsfollows, $queued=false, $name=null)
/*
Add a comment (application level) - create record, update appropriate counts, index it, send notifications.
$question should contain database record for the question this is part of (as direct or comment on Q's answer).
......@@ -199,11 +224,15 @@
$parent=$question; // for backwards compatibility with old answer parameter
$postid=qa_db_post_create($queued ? 'C_QUEUED' : 'C', $parent['postid'], $userid, isset($userid) ? null : $cookieid,
qa_remote_ip_address(), null, $content, $format, null, qa_combine_notify_email($userid, $notify, $email), $question['categoryid']);
qa_remote_ip_address(), null, $content, $format, null, qa_combine_notify_email($userid, $notify, $email),
$question['categoryid'], isset($userid) ? null : $name);
qa_db_posts_calc_category_path($postid);
if (!$queued) {
if ($queued) {
qa_db_queuedcount_update();
} else {
if ( ($question['type']=='Q') && (($parent['type']=='Q') || ($parent['type']=='A')) ) // only index if antecedents fully visible
qa_post_index($postid, 'C', $question['postid'], $parent['postid'], null, $content, $format, $text, null, $question['categoryid']);
......@@ -229,6 +258,7 @@
'format' => $format,
'text' => $text,
'categoryid' => $question['categoryid'],
'name' => $name,
'notify' => $notify,
'email' => $email,
));
......
......@@ -32,20 +32,19 @@
function qa_q_list_page_content($questions, $pagesize, $start, $count, $sometitle, $nonetitle,
$navcategories, $categoryid, $categoryqcount, $categorypathprefix, $feedpathprefix, $suggest,
$pagelinkparams=null, $categoryparams=null, $categoryisfavorite=null)
$pagelinkparams=null, $categoryparams=null, $dummy=null)
/*
Returns the $qa_content structure for a question list page showing $questions retrieved from the database.
If $pagesize is not null, it sets the max number of questions to display.
If $count is not null, pagination is determined by $start and $count.
The page title is $sometitle unless there are no questions shown, in which case it's $nonetitle.
$navcategories should contain the categories retrived from the database using qa_db_category_nav_selectspec(...) for
$categoryid, which is the current category shown (set $categoryisfavorite to whether the user has favorited it).
If $categorypathprefix is set, category navigation will be shown, with per-category question counts if
$categoryqcount is true. The nav links will have the prefix $categorypathprefix and possible extra $categoryparams.
If $feedpathprefix is set, the page has an RSS feed whose URL uses that prefix.
If there are no links to other pages, $suggest is used to suggest what the user should do.
The $pagelinkparams are passed through to qa_html_page_links(...) which creates links for page 2, 3, etc..
Returns the $qa_content structure for a question list page showing $questions retrieved from the
database. If $pagesize is not null, it sets the max number of questions to display. If $count is
not null, pagination is determined by $start and $count. The page title is $sometitle unless
there are no questions shown, in which case it's $nonetitle. $navcategories should contain the
categories retrived from the database using qa_db_category_nav_selectspec(...) for $categoryid,
which is the current category shown. If $categorypathprefix is set, category navigation will be
shown, with per-category question counts if $categoryqcount is true. The nav links will have the
prefix $categorypathprefix and possible extra $categoryparams. If $feedpathprefix is set, the
page has an RSS feed whose URL uses that prefix. If there are no links to other pages, $suggest
is used to suggest what the user should do. The $pagelinkparams are passed through to
qa_html_page_links(...) which creates links for page 2, 3, etc..
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
......@@ -70,6 +69,10 @@
$qa_content['q_list']['form']=array(
'tags' => 'METHOD="POST" ACTION="'.qa_self_html().'"',
'hidden' => array(
'code' => qa_get_form_security_code('vote'),
),
);
$qa_content['q_list']['qs']=array();
......@@ -77,19 +80,24 @@
if (count($questions)) {
$qa_content['title']=$sometitle;
$options=qa_post_html_defaults('Q');
$defaults=qa_post_html_defaults('Q');
if (isset($categorypathprefix))
$options['categorypathprefix']=$categorypathprefix;
$defaults['categorypathprefix']=$categorypathprefix;
foreach ($questions as $question)
$qa_content['q_list']['qs'][]=qa_any_to_q_html_fields($question, $userid, qa_cookie_get(), $usershtml, null, $options);
$qa_content['q_list']['qs'][]=qa_any_to_q_html_fields($question, $userid, qa_cookie_get(),
$usershtml, null, qa_post_html_options($question, $defaults));
} else
$qa_content['title']=$nonetitle;
if (isset($userid) && isset($categoryid) && isset($categoryisfavorite)) {
$favoritemap=qa_get_favorite_non_qs_map();
$categoryisfavorite=@$favoritemap['category'][$navcategories[$categoryid]['backpath']] ? true : false;
if (isset($userid) && isset($categoryid) && isset($categoryisfavorite))
$qa_content['favorite']=qa_favorite_form(QA_ENTITY_CATEGORY, $categoryid, $categoryisfavorite,
qa_lang_sub($categoryisfavorite ? 'main/remove_x_favorites' : 'main/add_category_x_favorites', $navcategories[$categoryid]['title']));
}
if (isset($count) && isset($pagesize))
$qa_content['page_links']=qa_html_page_links(qa_request(), $start, $pagesize, $count, qa_opt('pages_prev_next'), $pagelinkparams);
......
......@@ -34,7 +34,7 @@
^tagwords (all): index of words in tags of posts (a tag can contain multiple words)
^posttags (all): index tags of posts
^words (all): list of words used for indexes
^options (title=cache_qcount|cache_acount|cache_ccount|cache_tagcount|cache_unaqcount): total Qs, As, Cs, tags, unanswered Qs
^options (title=cache_*): cached values for various things (e.g. counting questions)
Recalculated in dorecountposts:
==============================
......@@ -70,6 +70,7 @@
require_once QA_INCLUDE_DIR.'qa-db-points.php';
require_once QA_INCLUDE_DIR.'qa-db-selects.php';
require_once QA_INCLUDE_DIR.'qa-db-admin.php';
require_once QA_INCLUDE_DIR.'qa-db-users.php';
require_once QA_INCLUDE_DIR.'qa-app-options.php';
require_once QA_INCLUDE_DIR.'qa-app-post-create.php';
require_once QA_INCLUDE_DIR.'qa-app-post-update.php';
......@@ -228,6 +229,7 @@
case 'dorecalcpoints_usercount':
qa_db_userpointscount_update(); // for progress update - not necessarily accurate
qa_db_uapprovecount_update(); // needs to be somewhere and this is the most appropriate place
qa_recalc_transition($state, 'dorecalcpoints_recalc');
break;
......@@ -294,7 +296,16 @@
foreach ($posts as $postid => $post) {
$followonq=($post['basetype']=='Q') && ($postid!=$questionid);
qa_create_event_for_q_user($questionid, $postid, $followonq ? QA_UPDATE_FOLLOWS : null, $post['userid'], @$posts[$post['parentid']]['userid'], $post['created']);
if ($followonq)
$updatetype=QA_UPDATE_FOLLOWS;
elseif ( ($post['basetype']=='C') && (@$posts[$post['parentid']]['basetype']=='Q') )
$updatetype=QA_UPDATE_C_FOR_Q;
elseif ( ($post['basetype']=='C') && (@$posts[$post['parentid']]['basetype']=='A') )
$updatetype=QA_UPDATE_C_FOR_A;
else
$updatetype=null;
qa_create_event_for_q_user($questionid, $postid, $updatetype, $post['userid'], @$posts[$post['parentid']]['userid'], $post['created']);
if (isset($post['updated']) && !$followonq)
qa_create_event_for_q_user($questionid, $postid, $post['updatetype'], $post['lastuserid'], $post['userid'], $post['updated']);
......@@ -323,7 +334,7 @@
foreach ($comments as $comment) {
foreach ($keyuserids as $keyuserid => $dummy)
if ( ($keyuserid != $comment['userid']) && ($keyuserid != @$posts[$parentid]['userid']) )
qa_db_event_create_not_entity($keyuserid, $questionid, $comment['postid'], null, $comment['userid'], $comment['created']);
qa_db_event_create_not_entity($keyuserid, $questionid, $comment['postid'], QA_UPDATE_FOLLOWS, $comment['userid'], $comment['created']);
if (isset($comment['userid']))
$keyuserids[$comment['userid']]=true;
......@@ -460,6 +471,51 @@
} else
qa_recalc_transition($state, 'dodeletehidden_complete');
break;
case 'doblobstodisk':
qa_recalc_transition($state, 'doblobstodisk_move');
break;
case 'doblobstodisk_move':
$blob=qa_db_get_next_blob_in_db($next);
if (isset($blob)) {
require_once QA_INCLUDE_DIR.'qa-app-blobs.php';
require_once QA_INCLUDE_DIR.'qa-db-blobs.php';
if (qa_write_blob_file($blob['blobid'], $blob['content'], $blob['format']))
qa_db_blob_set_content($blob['blobid'], null);
$next=1+$blob['blobid'];
$done++;
$continue=true;
} else
qa_recalc_transition($state, 'doblobstodisk_complete');
break;
case 'doblobstodb':
qa_recalc_transition($state, 'doblobstodb_move');
break;
case 'doblobstodb_move':
$blob=qa_db_get_next_blob_on_disk($next);
if (isset($blob)) {
require_once QA_INCLUDE_DIR.'qa-app-blobs.php';
require_once QA_INCLUDE_DIR.'qa-db-blobs.php';
$content=qa_read_blob_file($blob['blobid'], $blob['format']);
qa_db_blob_set_content($blob['blobid'], $content);
qa_delete_blob_file($blob['blobid'], $blob['format']);
$next=1+$blob['blobid'];
$done++;
$continue=true;
} else
qa_recalc_transition($state, 'doblobstodb_complete');
break;
default:
$state='';
......@@ -530,6 +586,14 @@
case 'dodeletehidden_questions':
$length=count(qa_db_posts_get_for_deleting('Q'));
break;
case 'doblobstodisk_move':
$length=qa_db_count_blobs_in_db();
break;
case 'doblobstodb_move':
$length=qa_db_count_blobs_on_disk();
break;
default:
$length=0;
......@@ -676,6 +740,19 @@
case 'dodeletehidden_complete':
$message=qa_lang('admin/delete_hidden_complete');
break;
case 'doblobstodisk_move':
case 'doblobstodb_move':
$message=strtr(qa_lang('admin/blobs_move_moved'), array(
'^1' => number_format($done),
'^2' => number_format($length)
));
break;
case 'doblobstodisk_complete':
case 'doblobstodb_complete':
$message=qa_lang('admin/blobs_move_complete');
break;
default:
$message='';
......
......@@ -84,7 +84,7 @@
// Perform the appropriate database queries
@list($postidfull, $postidtype, $postidquestion, $pageidpage)=qa_db_select_with_pending(
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,
......
......@@ -44,13 +44,18 @@
define('QA_UPDATE_CATEGORY', 'A'); // questions only, category changed
define('QA_UPDATE_CLOSED', 'C'); // questions only, closed or reopened
define('QA_UPDATE_CONTENT', 'E'); // title or content edited
define('QA_UPDATE_FOLLOWS', 'F'); // questions only (this is only set in streams tables, not on post)
define('QA_UPDATE_PARENT', 'M'); // e.g. comment moved when converting its parent answer to a comment
define('QA_UPDATE_SELECTED', 'S'); // answers only, removed if unselected
define('QA_UPDATE_TAGS', 'T'); // questions only
define('QA_UPDATE_TYPE', 'Y'); // e.g. answer to comment
define('QA_UPDATE_VISIBLE', 'H'); // hidden or reshown
// Character codes for types of update that only appear in the streams tables, not on the posts themselves
define('QA_UPDATE_FOLLOWS', 'F'); // if a new question was asked related to one of its answers, or for a comment that follows another
define('QA_UPDATE_C_FOR_Q', 'U'); // if comment created was on a question of the user whose stream this appears in
define('QA_UPDATE_C_FOR_A', 'N'); // if comment created was on an answer of the user whose stream this appears in
/*
Omit PHP closing tag to help avoid accidental output
......
<?php
/*
Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/
File: qa-include/qa-app-upload.php
Version: See define()s at top of qa-include/qa-base.php
Description: Application-level file upload functionality
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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;
}
function qa_get_max_upload_size()
/*
Return the maximum size of file that can be uploaded, based on database and PHP limits
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$mindb=16777215; // from MEDIUMBLOB column type
$minphp=trim(ini_get('upload_max_filesize'));
switch (strtolower(substr($minphp, -1))) {
case 'g':
$minphp*=1024;
case 'm':
$minphp*=1024;
case 'k':
$minphp*=1024;
}
return min($mindb, $minphp);
}
function qa_upload_file_one($maxfilesize=null, $onlyimage=false, $imagemaxwidth=null, $imagemaxheight=null)
{
$file=reset($_FILES);
return qa_upload_file($file['tmp_name'], $file['name'], $maxfilesize, $onlyimage, $imagemaxwidth, $imagemaxheight);
}
function qa_upload_file($localfilename, $sourcefilename, $maxfilesize=null, $onlyimage=false, $imagemaxwidth=null, $imagemaxheight=null)
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$result=array();
// Check per-user upload limits
require_once QA_INCLUDE_DIR.'qa-app-users.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php';
switch (qa_user_permit_error(null, QA_LIMIT_UPLOADS))
{
case 'limit':
$result['error']=qa_lang('main/upload_limit');
return $result;
case false:
qa_limits_increment(qa_get_logged_in_userid(), QA_LIMIT_UPLOADS);
break;
default:
$result['error']=qa_lang('users/no_permission');
return $result;
}
// Check the uploaded file is not too large
$filesize=filesize($localfilename);
if (isset($maxfilesize))
$maxfilesize=min($maxfilesize, qa_get_max_upload_size());
else
$maxfilesize=qa_get_max_upload_size();
if ( ($filesize<=0) || ($filesize>$maxfilesize) ) { // if file was too big for PHP, $filesize will be zero
$result['error']=qa_lang_sub('main/max_upload_size_x', number_format($maxfilesize/1048576, 1).'MB');
return $result;
}
// Find out what type of source file was uploaded and if appropriate, check it's an image and get preliminary size measure
$pathinfo=pathinfo($sourcefilename);
$format=strtolower(@$pathinfo['extension']);
$isimage=($format=='png') || ($format=='gif') || ($format=='jpeg') || ($format=='jpg'); // allowed image extensions
if ($isimage) {
$imagesize=@getimagesize($localfilename);
if (is_array($imagesize)) {
$result['width']=$imagesize[0];
$result['height']=$imagesize[1];
switch ($imagesize['2']) { // reassign format based on actual content, if we can
case IMAGETYPE_GIF:
$format='gif';
break;
case IMAGETYPE_JPEG:
$format='jpeg';
break;
case IMAGETYPE_PNG:
$format='png';
break;
}
}
}
$result['format']=$format;
if ($onlyimage)
if ( (!$isimage) || !is_array($imagesize) ) {
$result['error']=qa_lang_sub('main/image_not_read', 'GIF, JPG, PNG');
return $result;
}
// Read in the raw file contents
$content=file_get_contents($localfilename);
// If appropriate, get more accurate image size and apply constraints to it
require_once QA_INCLUDE_DIR.'qa-util-image.php';
if ($isimage && qa_has_gd_image()) {
$image=@imagecreatefromstring($content);
if (is_resource($image)) {
$result['width']=$width=imagesx($image);
$result['height']=$height=imagesy($image);
if (isset($imagemaxwidth) || isset($imagemaxheight))
if (qa_image_constrain(
$width, $height,
isset($imagemaxwidth) ? $imagemaxwidth : $width,
isset($imagemaxheight) ? $imagemaxheight : $height
)) {
qa_gd_image_resize($image, $width, $height);
if (is_resource($image)) {
$content=qa_gd_image_jpeg($image);
$result['format']=$format='jpeg';
$result['width']=$width;
$result['height']=$height;
}
}
if (is_resource($image)) // might have been lost
imagedestroy($image);
}
}
// Create the blob and return
require_once QA_INCLUDE_DIR.'qa-app-blobs.php';
$userid=qa_get_logged_in_userid();
$cookieid=isset($userid) ? qa_cookie_get() : qa_cookie_get_create();
$result['blobid']=qa_create_blob($content, $format, $sourcefilename, $userid, $cookieid, qa_remote_ip_address());
if (!isset($result['blobid'])) {
$result['error']=qa_lang('main/general_error');
return $result;
}
$result['bloburl']=qa_get_blob_url($result['blobid'], true);
return $result;
}
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
......@@ -166,6 +166,7 @@
$userid=qa_db_user_create($email, $password, $handle, $level, qa_remote_ip_address());
qa_db_points_update_ifuser($userid, null);
qa_db_uapprovecount_update();
if ($confirmed)
qa_db_user_set_flag($userid, QA_USER_FLAGS_EMAIL_CONFIRMED, true);
......@@ -186,6 +187,9 @@
} else
$confirm='';
if (qa_opt('moderate_users') && qa_opt('approve_user_required') && ($level<QA_USER_LEVEL_EXPERT))
qa_db_user_set_flag($userid, QA_USER_FLAGS_MUST_APPROVE, true);
qa_send_notification($userid, $email, $handle, qa_lang('emails/welcome_subject'), qa_lang('emails/welcome_body'), array(
'^password' => isset($password) ? $password : qa_lang('users/password_to_set'),
'^url' => qa_opt('site_url'),
......@@ -218,6 +222,7 @@
$postids=qa_db_uservoteflag_user_get($userid); // posts this user has flagged or voted on, whose counts need updating
qa_db_user_delete($userid);
qa_db_uapprovecount_update();
foreach ($postids as $postid) { // hoping there aren't many of these - saves a lot of new SQL code...
qa_db_post_recount_votes($postid);
......@@ -263,7 +268,7 @@
$emailcode=qa_db_user_rand_emailcode();
qa_db_user_set($userid, 'emailcode', $emailcode);
return qa_path('confirm', array('c' => $emailcode, 'u' => $handle), qa_opt('site_url'));
return qa_path_absolute('confirm', array('c' => $emailcode, 'u' => $handle));
}
......@@ -285,6 +290,41 @@
'email' => $email,
));
}
function qa_set_user_level($userid, $handle, $level, $oldlevel)
{
require_once QA_INCLUDE_DIR.'qa-db-users.php';
if ($level!=$oldlevel) {
qa_db_user_set($userid, 'level', $level);
qa_db_uapprovecount_update();
if ($level>=QA_USER_LEVEL_APPROVED)
qa_db_user_set_flag($userid, QA_USER_FLAGS_MUST_APPROVE, false);
qa_report_event('u_level', qa_get_logged_in_userid(), qa_get_logged_in_handle(), qa_cookie_get(), array(
'userid' => $userid,
'handle' => $handle,
'level' => $level,
'oldlevel' => $oldlevel,
));
}
}
function qa_set_user_blocked($userid, $handle, $blocked)
{
require_once QA_INCLUDE_DIR.'qa-db-users.php';
qa_db_user_set_flag($userid, QA_USER_FLAGS_USER_BLOCKED, $blocked);
qa_db_uapprovecount_update();
qa_report_event($blocked ? 'u_block' : 'u_unblock', qa_get_logged_in_userid(), qa_get_logged_in_handle(), qa_cookie_get(), array(
'userid' => $userid,
'handle' => $handle,
));
}
function qa_start_reset_user($userid)
......@@ -305,7 +345,7 @@
if (!qa_send_notification($userid, $userinfo['email'], $userinfo['handle'], qa_lang('emails/reset_subject'), qa_lang('emails/reset_body'), array(
'^code' => $userinfo['emailcode'],
'^url' => qa_path('reset', array('c' => $userinfo['emailcode'], 'e' => $userinfo['email']), qa_opt('site_url')),
'^url' => qa_path_absolute('reset', array('c' => $userinfo['emailcode'], 'e' => $userinfo['email'])),
)))
qa_fatal_error('Could not send reset password email');
}
......@@ -366,9 +406,9 @@
$imagedata=qa_image_constrain_data($imagedata, $width, $height, qa_opt('avatar_store_size'));
if (isset($imagedata)) {
require_once QA_INCLUDE_DIR.'qa-db-blobs.php';
require_once QA_INCLUDE_DIR.'qa-app-blobs.php';
$newblobid=qa_db_blob_create($imagedata, 'jpeg', null, $userid, null, qa_remote_ip_address());
$newblobid=qa_create_blob($imagedata, 'jpeg', null, $userid, null, qa_remote_ip_address());
if (isset($newblobid)) {
qa_db_user_set($userid, 'avatarblobid', $newblobid);
......@@ -378,7 +418,7 @@
qa_db_user_set_flag($userid, QA_USER_FLAGS_SHOW_GRAVATAR, false);
if (isset($oldblobid))
qa_db_blob_delete($oldblobid);
qa_delete_blob($oldblobid);
return true;
}
......
......@@ -38,6 +38,9 @@
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
// The 'login', 'confirm', 'limit', 'userblock' and 'ipblock' permission errors are reported to the user here.
// Others ('approve', 'level') prevent the buttons being clickable in the first place, in qa_get_vote_view(...)
require_once QA_INCLUDE_DIR.'qa-app-users.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php';
......@@ -47,11 +50,11 @@
qa_opt(($post['basetype']=='Q') ? 'voting_on_qs' : 'voting_on_as') &&
( (!isset($post['userid'])) || (!isset($userid)) || ($post['userid']!=$userid) )
) {
$permiterror=qa_user_permit_error(($post['basetype']=='Q') ? 'permit_vote_q' : 'permit_vote_a', QA_LIMIT_VOTES);
$permiterror=qa_user_post_permit_error(($post['basetype']=='Q') ? 'permit_vote_q' : 'permit_vote_a', $post, QA_LIMIT_VOTES);
$errordownonly=(!$permiterror) && ($vote<0);
if ($errordownonly)
$permiterror=qa_user_permit_error('permit_vote_down');
$permiterror=qa_user_post_permit_error('permit_vote_down', $post);
switch ($permiterror) {
case 'login':
......@@ -144,6 +147,9 @@
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
// The 'login', 'confirm', 'limit', 'userblock' and 'ipblock' permission errors are reported to the user here.
// Others ('approve', 'level') prevent the flag button being shown, in qa_page_q_post_rules(...)
require_once QA_INCLUDE_DIR.'qa-db-selects.php';
require_once QA_INCLUDE_DIR.'qa-app-options.php';
require_once QA_INCLUDE_DIR.'qa-app-users.php';
......@@ -155,7 +161,7 @@
( (!isset($post['userid'])) || (!isset($userid)) || ($post['userid']!=$userid) )
) {
switch (qa_user_permit_error('permit_flag', QA_LIMIT_FLAGS)) {
switch (qa_user_post_permit_error('permit_flag', $post, QA_LIMIT_FLAGS)) {
case 'login':
return qa_insert_login_links(qa_lang_html('question/flag_must_login'), $topage);
break;
......@@ -192,9 +198,11 @@
require_once QA_INCLUDE_DIR.'qa-db-votes.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php';
require_once QA_INCLUDE_DIR.'qa-db-post-update.php';
qa_db_userflag_set($oldpost['postid'], $userid, true);
qa_db_post_recount_flags($oldpost['postid']);
qa_db_flaggedcount_update();
switch ($oldpost['basetype']) {
case 'Q':
......@@ -234,9 +242,11 @@
require_once QA_INCLUDE_DIR.'qa-db-votes.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php';
require_once QA_INCLUDE_DIR.'qa-db-post-update.php';
qa_db_userflag_set($oldpost['postid'], $userid, false);
qa_db_post_recount_flags($oldpost['postid']);
qa_db_flaggedcount_update();
switch ($oldpost['basetype']) {
case 'Q':
......@@ -269,9 +279,11 @@
require_once QA_INCLUDE_DIR.'qa-db-votes.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php';
require_once QA_INCLUDE_DIR.'qa-db-post-update.php';
qa_db_userflags_clear_all($oldpost['postid']);
qa_db_post_recount_flags($oldpost['postid']);
qa_db_flaggedcount_update();
switch ($oldpost['basetype']) {
case 'Q':
......
......@@ -25,8 +25,8 @@
*/
define('QA_VERSION', '1.5.4'); // also used as suffix for .js and .css requests
define('QA_BUILD_DATE', '2012-11-29');
define('QA_VERSION', '1.6-beta-1'); // also used as suffix for .js and .css requests
define('QA_BUILD_DATE', '2013-06-06');
// Execution section of this file - remainder contains function definitions
......@@ -314,7 +314,8 @@
$functionindex=array();
foreach ($qa_override_files as $index => $override) {
$functionsphp=file_get_contents($override['directory'].$override['include']);
$filename=$override['directory'].$override['include'];
$functionsphp=file_get_contents($filename);
preg_match_all('/\Wfunction\s+(qa_[a-z_]+)\s*\(/im', $functionsphp, $rawmatches, PREG_PATTERN_ORDER|PREG_OFFSET_CAPTURE);
......@@ -344,7 +345,7 @@
// echo '<PRE STYLE="text-align:left;">'.htmlspecialchars($functionsphp).'</PRE>'; // to debug munged code
eval('?'.'>'.$functionsphp);
qa_eval_from_file($functionsphp, $filename);
}
}
......@@ -493,6 +494,31 @@
// Low-level functions used throughout Q2A
function qa_eval_from_file($contents, $filename)
{
// could also use ini_set('error_append_string') but apparently it doesn't work for errors logged on disk
global $php_errormsg;
$oldtrackerrors=@ini_set('track_errors', 1);
$php_errormsg=null;
eval('?'.'>'.$contents);
if (strlen($php_errormsg)) {
switch (strtolower(@ini_get('display_errors'))) {
case 'on': case '1': case 'yes': case 'true': case 'stdout': case 'stderr':
echo ' of '.qa_html($filename)."\n";
break;
}
@error_log('PHP Question2Answer more info: '.$php_errormsg." in eval()'d code from ".qa_html($filename));
}
@ini_set('track_errors', $oldtrackerrors);
}
function qa_call($function, $args)
/*
Call $function with the arguments in the $args array (doesn't work with call-by-reference functions)
......@@ -574,8 +600,7 @@
$backtrace=array_reverse(array_slice(debug_backtrace(), 1));
foreach ($backtrace as $trace)
echo '<FONT COLOR="#'.((strpos(@$trace['file'], '/qa-plugin/')!==false) ? 'f00' : '999').'">'.
qa_html(@$trace['function'].'() '.@$trace['file'].':'.@$trace['line']).'</FONT><BR>';
qa_html(@$trace['function'].'() in '.basename(@$trace['file']).':'.@$trace['line']).'</FONT><BR>';
qa_exit('error');
}
......@@ -635,7 +660,7 @@
$object=new $module['class'];
if (method_exists($object, 'load_module'))
$object->load_module($module['directory'], qa_path_to_root().$module['urltoroot']);
$object->load_module($module['directory'], qa_path_to_root().$module['urltoroot'], $type, $name);
$qa_modules[$type][$name]['object']=$object;
return $object;
......@@ -742,6 +767,12 @@
}
function qa_xml($string)
{
return htmlspecialchars(preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', (string)$string));
}
function qa_js($value, $forcequotes=false)
/*
Return JavaScript representation of $value, putting in quotes if non-numeric or if $forcequote is true
......@@ -856,12 +887,13 @@
function qa_clicked($name)
/*
Return true if form button $name was clicked (as TYPE=SUBMIT/IMAGE) to create this page request.
Return true if form button $name was clicked (as TYPE=SUBMIT/IMAGE) to create this page request, or if a
simulated click was sent for the button (via 'qa_click' POST field)
*/
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return isset($_POST[$name]) || isset($_POST[$name.'_x']);
return isset($_POST[$name]) || isset($_POST[$name.'_x']) || (qa_post_text('qa_click')==$name);
}
......@@ -1166,6 +1198,12 @@
{
return qa_html(qa_path($request, $params, $rooturl, $neaturls, $anchor));
}
function qa_path_absolute($request, $params=null, $anchor=null)
{
return qa_path($request, $params, qa_opt('site_url'), null, $anchor);
}
function qa_q_request($questionid, $title)
......@@ -1227,7 +1265,7 @@
{
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
if ( (($showtype=='A') || ($showtype=='C')) && isset($showid)) {
if ( (($showtype=='Q') || ($showtype=='A') || ($showtype=='C')) && isset($showid)) {
$params=array('show' => $showid); // due to pagination
$anchor=qa_anchor($showtype, $showid);
......
......@@ -45,11 +45,11 @@
// Output the blob in question
require_once QA_INCLUDE_DIR.'qa-db-blobs.php';
require_once QA_INCLUDE_DIR.'qa-app-blobs.php';
qa_db_connect('qa_blob_db_fail_handler');
$blob=qa_db_blob_read(qa_get('qa_blobid'));
$blob=qa_read_blob(qa_get('qa_blobid'));
if (isset($blob)) {
header('Cache-Control: max-age=2592000, public'); // allows browsers and proxies to cache the blob
......
......@@ -61,7 +61,7 @@
echo '<H1>Checking US English files in <code>qa-include</code>...</H1>';
$includefiles=glob(QA_INCLUDE_DIR.'qa-*.php');
$includefiles=array_merge(glob(QA_INCLUDE_DIR.'qa-*.php'), glob(QA_PLUGIN_DIR.'*/qa-*.php'));
$definite=array();
$probable=array();
......
......@@ -138,7 +138,7 @@
*/
{
return qa_db_read_all_values(qa_db_query_sub(
"SELECT postid FROM ^posts WHERE userid=# AND type IN ('Q', 'A', 'C')",
"SELECT postid FROM ^posts WHERE userid=# AND type IN ('Q', 'A', 'C', 'Q_QUEUED', 'A_QUEUED', 'C_QUEUED')",
$userid
));
}
......@@ -150,7 +150,7 @@
*/
{
return qa_db_read_all_values(qa_db_query_sub(
"SELECT postid FROM ^posts WHERE createip=INET_ATON($) AND type IN ('Q', 'A', 'C')",
"SELECT postid FROM ^posts WHERE createip=INET_ATON($) AND type IN ('Q', 'A', 'C', 'Q_QUEUED', 'A_QUEUED', 'C_QUEUED')",
$ip
));
}
......@@ -169,6 +169,45 @@
else
return array();
}
function qa_db_get_unapproved_users($count)
{
$results=qa_db_read_all_assoc(qa_db_query_sub(
"SELECT ^users.userid, UNIX_TIMESTAMP(created) AS created, INET_NTOA(createip) AS createip, email, handle, title, content FROM ^users LEFT JOIN ^userprofile ON ^users.userid=^userprofile.userid AND LENGTH(content)>0 WHERE level<# AND NOT (flags&#) ORDER BY created DESC LIMIT #",
QA_USER_LEVEL_APPROVED, QA_USER_FLAGS_USER_BLOCKED, $count
));
$users=array();
foreach ($results as $result) {
$userid=$result['userid'];
if (!isset($users[$userid])) {
$users[$result['userid']]=$result;
$users[$result['userid']]['profile']=array();
unset($users[$userid]['title']);
unset($users[$userid]['content']);
}
if (isset($result['title']) && isset($result['content']))
$users[$userid]['profile'][$result['title']]=$result['content'];
}
return $users;
}
function qa_db_has_blobs_on_disk()
{
return count(qa_db_read_all_values(qa_db_query_sub('SELECT blobid FROM ^blobs WHERE content IS NULL LIMIT 1'))) ? true : false;
}
function qa_db_has_blobs_in_db()
{
return count(qa_db_read_all_values(qa_db_query_sub('SELECT blobid FROM ^blobs WHERE content IS NOT NULL LIMIT 1'))) ? true : false;
}
function qa_db_category_last_pos($parentid)
......@@ -442,7 +481,7 @@
}
function qa_db_userfield_create($title, $content, $flags)
function qa_db_userfield_create($title, $content, $flags, $permit=null)
/*
Create a new user field with (internal) tag $title, label $content, and $flags in the database
*/
......@@ -450,22 +489,22 @@
$position=qa_db_read_one_value(qa_db_query_sub('SELECT 1+COALESCE(MAX(position), 0) FROM ^userfields'));
qa_db_query_sub(
'INSERT INTO ^userfields (title, content, position, flags) VALUES ($, $, #, #)',
$title, $content, $position, $flags
'INSERT INTO ^userfields (title, content, position, flags, permit) VALUES ($, $, #, #, #)',
$title, $content, $position, $flags, $permit
);
return qa_db_last_insert_id();
}
function qa_db_userfield_set_fields($fieldid, $content, $flags)
function qa_db_userfield_set_fields($fieldid, $content, $flags, $permit=null)
/*
Change the user field $fieldid to have label $content and $flags in the database (the title column cannot be changed once set)
*/
{
qa_db_query_sub(
'UPDATE ^userfields SET content=$, flags=# WHERE fieldid=#',
$content, $flags, $fieldid
'UPDATE ^userfields SET content=$, flags=#, permit=# WHERE fieldid=#',
$content, $flags, $permit, $fieldid
);
}
......
......@@ -30,7 +30,7 @@
}
function qa_db_blob_create($content, $format, $filename=null, $userid=null, $cookieid=null, $ip=null)
function qa_db_blob_create($content, $format, $sourcefilename=null, $userid=null, $cookieid=null, $ip=null)
/*
Create a new blob in the database with $content and $format, returning its blobid
*/
......@@ -45,7 +45,7 @@
qa_db_query_sub(
'INSERT INTO ^blobs (blobid, format, content, filename, userid, cookieid, createip, created) VALUES (#, $, $, $, $, #, INET_ATON($), NOW())',
$blobid, $format, $content, $filename, $userid, $cookieid, $ip
$blobid, $format, $content, $sourcefilename, $userid, $cookieid, $ip
);
return $blobid;
......@@ -69,6 +69,15 @@
}
function qa_db_blob_set_content($blobid, $content)
{
qa_db_query_sub(
'UPDATE ^blobs SET content=$ WHERE blobid=#',
$content, $blobid
);
}
function qa_db_blob_delete($blobid)
/*
Delete blob $blobid in the database
......
......@@ -117,7 +117,7 @@
Add an event to the event stream for $userid which is not related to an entity they are following (but rather a
notification which is relevant for them, e.g. if someone answers their question). The event of type $updatetype
relates to $lastpostid whose antecedent question is $questionid, and was caused by $lastuserid. Pass a unix
$timestamp for the event time or leave as null to use now. Also handles truncation.
$timestamp for the event time or leave as null to use now. Also handles truncation of event streams.
*/
{
require_once QA_INCLUDE_DIR.'qa-app-updates.php';
......
......@@ -39,6 +39,7 @@
@define('QA_DB_MAX_CONTENT_LENGTH', 8000);
@define('QA_DB_MAX_FORMAT_LENGTH', 20);
@define('QA_DB_MAX_TAGS_LENGTH', 800);
@define('QA_DB_MAX_NAME_LENGTH', 40);
@define('QA_DB_MAX_WORD_LENGTH', 80);
@define('QA_DB_MAX_CAT_PAGE_TITLE_LENGTH', 80);
@define('QA_DB_MAX_CAT_PAGE_TAGS_LENGTH', 200);
......
......@@ -30,18 +30,27 @@
}
function qa_db_message_create($fromuserid, $touserid, $content, $format)
function qa_db_message_create($fromuserid, $touserid, $content, $format, $public=false)
/*
Record a private message sent from $fromuserid to $touserid with $content in $format
*/
{
qa_db_query_sub(
'INSERT INTO ^messages (fromuserid, touserid, content, format, created) VALUES (#, #, $, $, NOW())',
$fromuserid, $touserid, $content, $format
'INSERT INTO ^messages (type, fromuserid, touserid, content, format, created) VALUES ($, #, #, $, $, NOW())',
$public ? 'PUBLIC' : 'PRIVATE', $fromuserid, $touserid, $content, $format
);
return qa_db_last_insert_id();
}
function qa_db_message_delete($messageid)
{
qa_db_query_sub(
'DELETE FROM ^messages WHERE messageid=#',
$messageid
);
}
/*
......
......@@ -30,14 +30,15 @@
}
function qa_db_post_create($type, $parentid, $userid, $cookieid, $ip, $title, $content, $format, $tagstring, $notify, $categoryid=null)
function qa_db_post_create($type, $parentid, $userid, $cookieid, $ip, $title, $content, $format, $tagstring, $notify, $categoryid=null, $name=null)
/*
Create a new post in the database and return its ID (based on auto-incrementing)
*/
{
qa_db_query_sub(
'INSERT INTO ^posts (categoryid, type, parentid, userid, cookieid, createip, title, content, format, tags, notify, created) VALUES (#, $, #, $, #, INET_ATON($), $, $, $, $, $, NOW())',
$categoryid, $type, $parentid, $userid, $cookieid, $ip, $title, $content, $format, $tagstring, $notify
'INSERT INTO ^posts (categoryid, type, parentid, userid, cookieid, createip, title, content, format, tags, notify, name, created) '.
'VALUES (#, $, #, $, #, INET_ATON($), $, $, $, $, $, $, NOW())',
$categoryid, $type, $parentid, $userid, $cookieid, $ip, $title, $content, $format, $tagstring, $notify, $name
);
return qa_db_last_insert_id();
......@@ -352,6 +353,13 @@
if (qa_should_update_counts())
qa_db_query_sub("REPLACE ^options (title, content) SELECT 'cache_unupaqcount', COUNT(*) FROM ^posts WHERE type='Q' AND amaxvote=0");
}
function qa_db_queuedcount_update()
{
if (qa_should_update_counts())
qa_db_query_sub("REPLACE ^options (title, content) SELECT 'cache_queuedcount', COUNT(*) FROM ^posts WHERE type IN ('Q_QUEUED', 'A_QUEUED', 'C_QUEUED')");
}
/*
Omit PHP closing tag to help avoid accidental output
......
......@@ -113,21 +113,21 @@
}
function qa_db_post_set_content($postid, $title, $content, $format, $tagstring, $notify, $lastuserid=null, $lastip=null, $updatetype=QA_UPDATE_CONTENT)
function qa_db_post_set_content($postid, $title, $content, $format, $tagstring, $notify, $lastuserid=null, $lastip=null, $updatetype=QA_UPDATE_CONTENT, $name=null)
/*
Set the text fields in the database of $postid to $title, $content, $tagstring and $notify, and record
that $lastuserid did it from $lastip (if at least one is specified) with $updatetype.
*/
{
if (isset($lastuserid) || isset($lastip))
if (isset($lastuserid) || isset($lastip)) // use COALESCE() for name since $name=null means it should not be modified (for backwards compatibility)
qa_db_query_sub(
'UPDATE ^posts SET title=$, content=$, format=$, tags=$, notify=$, updated=NOW(), updatetype=$, lastuserid=$, lastip=INET_ATON($) WHERE postid=#',
$title, $content, $format, $tagstring, $notify, $updatetype, $lastuserid, $lastip, $postid
'UPDATE ^posts SET title=$, content=$, format=$, tags=$, name=COALESCE($, name), notify=$, updated=NOW(), updatetype=$, lastuserid=$, lastip=INET_ATON($) WHERE postid=#',
$title, $content, $format, $tagstring, $name, $notify, $updatetype, $lastuserid, $lastip, $postid
);
else
qa_db_query_sub(
'UPDATE ^posts SET title=$, content=$, format=$, tags=$, notify=$ WHERE postid=#',
$title, $content, $format, $tagstring, $notify, $postid
'UPDATE ^posts SET title=$, content=$, format=$, tags=$, name=COALESCE($, name), notify=$ WHERE postid=#',
$title, $content, $format, $tagstring, $name, $notify, $postid
);
}
......@@ -193,6 +193,21 @@
}
function qa_db_post_set_updated($postid, $updated)
{
if (isset($updated))
qa_db_query_sub(
'UPDATE ^posts SET updated=FROM_UNIXTIME(#) WHERE postid=#',
$updated, $postid
);
else
qa_db_query_sub(
'UPDATE ^posts SET updated=NOW() WHERE postid=#',
$postid
);
}
function qa_db_post_delete($postid)
/*
Deletes post $postid from the database (will also delete any votes on the post due to foreign key cascading)
......@@ -330,6 +345,12 @@
return array();
}
function qa_db_flaggedcount_update()
{
if (qa_should_update_counts())
qa_db_query_sub("REPLACE ^options (title, content) SELECT 'cache_flaggedcount', COUNT(*) FROM ^posts WHERE flagcount>0 AND type IN ('Q', 'A', 'C')");
}
/*
Omit PHP closing tag to help avoid accidental output
......
......@@ -377,7 +377,36 @@
$type.'_HIDDEN', $startpostid
));
}
// For moving blobs between database and disk...
function qa_db_count_blobs_in_db()
{
return qa_db_read_one_value(qa_db_query_sub('SELECT COUNT(*) FROM ^blobs WHERE content IS NOT NULL'));
}
function qa_db_get_next_blob_in_db($startblobid)
{
return qa_db_read_one_assoc(qa_db_query_sub(
'SELECT blobid, content, format FROM ^blobs WHERE blobid>=# AND content IS NOT NULL',
$startblobid
), true);
}
function qa_db_count_blobs_on_disk()
{
return qa_db_read_one_value(qa_db_query_sub('SELECT COUNT(*) FROM ^blobs WHERE content IS NULL'));
}
function qa_db_get_next_blob_on_disk($startblobid)
{
return qa_db_read_one_assoc(qa_db_query_sub(
'SELECT blobid, format FROM ^blobs WHERE blobid>=# AND content IS NULL',
$startblobid
), true);
}
/*
Omit PHP closing tag to help avoid accidental output
......
......@@ -273,7 +273,7 @@
*/
{
if ($sync) { // need to lock all tables since any could be used by a plugin's event module
$tables=qa_db_list_tables_lc();
$tables=qa_db_list_tables();
$locks=array();
foreach ($tables as $table)
......@@ -286,6 +286,21 @@
}
function qa_db_user_levels_set($userid, $userlevels)
{
qa_db_query_sub(
'DELETE FROM ^userlevels WHERE userid=$',
$userid
);
foreach ($userlevels as $userlevel)
qa_db_query_sub(
'REPLACE ^userlevels (userid, entitytype, entityid, level) VALUES ($, $, #, #)',
$userid, $userlevel['entitytype'], $userlevel['entityid'], $userlevel['level']
);
}
function qa_db_users_get_mailing_next($lastuserid, $count)
/*
Get the information required for sending a mailing to the next $count users with userids greater than $lastuserid
......@@ -296,6 +311,16 @@
$lastuserid, $count
));
}
function qa_db_uapprovecount_update()
{
if ( qa_should_update_counts() && !QA_FINAL_EXTERNAL_USERS )
qa_db_query_sub(
"REPLACE ^options (title, content) SELECT 'cache_uapprovecount', COUNT(*) FROM ^users WHERE level<# AND NOT (flags&#)",
QA_USER_LEVEL_APPROVED, QA_USER_FLAGS_USER_BLOCKED
);
}
/*
......
......@@ -131,6 +131,22 @@
));
}
function qa_db_uservoteflag_posts_get($postids)
{
if (QA_FINAL_EXTERNAL_USERS)
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT postid, userid, vote, flag FROM ^uservotes WHERE postid IN (#) AND ((vote!=0) OR (flag!=0))',
$postids
));
else
return qa_db_read_all_assoc(qa_db_query_sub(
'SELECT postid, handle, vote, flag FROM ^uservotes LEFT JOIN ^users ON ^uservotes.userid=^users.userid WHERE postid IN (#) AND ((vote!=0) OR (flag!=0))',
$postids
));
}
/*
Omit PHP closing tag to help avoid accidental output
......
......@@ -274,7 +274,7 @@
$prefix=QA_MYSQL_TABLE_PREFIX;
if (defined('QA_MYSQL_USERS_PREFIX'))
if (defined('QA_MYSQL_USERS_PREFIX')) {
switch (strtolower($rawname)) {
case 'users':
case 'userlogins':
......@@ -284,9 +284,12 @@
case 'cookies':
case 'blobs':
case 'cache':
case 'userlogins_ibfk_1': // also special cases for constraint names
case 'userprofile_ibfk_1':
$prefix=QA_MYSQL_USERS_PREFIX;
break;
}
}
return $prefix.$rawname;
}
......@@ -395,12 +398,13 @@
Return an array of the names of all tables in the Q2A database, converted to lower case
*/
{
$tables=qa_db_read_all_values(qa_db_query_raw('SHOW TABLES'));
foreach ($tables as $key => $table)
$tables[$key]=strtolower($table);
return $tables;
return array_map('strtolower', qa_db_list_tables());
}
function qa_db_list_tables()
{
return qa_db_read_all_values(qa_db_query_raw('SHOW TABLES'));
}
......
......@@ -69,6 +69,7 @@
break;
case 'u_message':
case 'u_wall_post':
qa_limits_increment($userid, QA_LIMIT_MESSAGES);
break;
}
......
......@@ -42,13 +42,14 @@
switch ($event) {
case 'q_post':
$followanswer=@$params['followanswer'];
$sendhandle=isset($handle) ? $handle : (strlen($params['name']) ? $params['name'] : qa_lang('main/anonymous'));
if (isset($followanswer['notify']) && !qa_post_is_by_user($followanswer, $userid, $cookieid)) {
$blockwordspreg=qa_get_block_words_preg();
$sendtext=qa_viewer_text($followanswer['content'], $followanswer['format'], array('blockwordspreg' => $blockwordspreg));
qa_send_notification($followanswer['userid'], $followanswer['notify'], @$followanswer['handle'], qa_lang('emails/a_followed_subject'), qa_lang('emails/a_followed_body'), array(
'^q_handle' => isset($handle) ? $handle : qa_lang('main/anonymous'),
'^q_handle' => $sendhandle,
'^q_title' => qa_block_words_replace($params['title'], $blockwordspreg),
'^a_content' => $sendtext,
'^url' => qa_q_path($params['postid'], $params['title'], true),
......@@ -57,7 +58,7 @@
if (qa_opt('notify_admin_q_post'))
qa_send_notification(null, qa_opt('feedback_email'), null, qa_lang('emails/q_posted_subject'), qa_lang('emails/q_posted_body'), array(
'^q_handle' => isset($handle) ? $handle : qa_lang('main/anonymous'),
'^q_handle' => $sendhandle,
'^q_title' => $params['title'], // don't censor title or content here since we want the admin to see bad words
'^q_content' => $params['text'],
'^url' => qa_q_path($params['postid'], $params['title'], true),
......@@ -71,7 +72,7 @@
if (isset($question['notify']) && !qa_post_is_by_user($question, $userid, $cookieid))
qa_send_notification($question['userid'], $question['notify'], @$question['handle'], qa_lang('emails/q_answered_subject'), qa_lang('emails/q_answered_body'), array(
'^a_handle' => isset($handle) ? $handle : qa_lang('main/anonymous'),
'^a_handle' => isset($handle) ? $handle : (strlen($params['name']) ? $params['name'] : qa_lang('main/anonymous')),
'^q_title' => $question['title'],
'^a_content' => qa_block_words_replace($params['text'], qa_get_block_words_preg()),
'^url' => qa_q_path($question['postid'], $question['title'], true, 'A', $params['postid']),
......@@ -101,7 +102,7 @@
}
$blockwordspreg=qa_get_block_words_preg();
$sendhandle=isset($handle) ? $handle : qa_lang('main/anonymous');
$sendhandle=isset($handle) ? $handle : (strlen($params['name']) ? $params['name'] : qa_lang('main/anonymous'));
$sendcontext=qa_block_words_replace($context, $blockwordspreg);
$sendtext=qa_block_words_replace($params['text'], $blockwordspreg);
$sendurl=qa_q_path($question['postid'], $question['title'], true, $parent['basetype'], $parent['postid']);
......@@ -152,32 +153,54 @@
case 'q_queue':
case 'q_requeue':
if (qa_opt('moderate_notify_admin'))
qa_send_notification(null, qa_opt('feedback_email'), null, qa_lang('emails/moderate_subject'), qa_lang('emails/moderate_body'), array(
'^p_handle' => isset($handle) ? $handle : qa_lang('main/anonymous'),
'^p_context' => trim(@$params['title']."\n\n".$params['text']),
'^url' => qa_q_path($params['postid'], $params['title'], true),
));
qa_send_notification(null, qa_opt('feedback_email'), null,
($event=='q_requeue') ? qa_lang('emails/remoderate_subject') : qa_lang('emails/moderate_subject'),
($event=='q_requeue') ? qa_lang('emails/remoderate_body') : qa_lang('emails/moderate_body'),
array(
'^p_handle' => isset($handle) ? $handle : (strlen($params['name']) ? $params['name'] :
(strlen(@$oldquestion['name']) ? $oldquestion['name'] : qa_lang('main/anonymous'))),
'^p_context' => trim(@$params['title']."\n\n".$params['text']),
'^url' => qa_q_path($params['postid'], $params['title'], true),
'^a_url' => qa_path_absolute('admin/moderate'),
)
);
break;
case 'a_queue':
case 'a_requeue':
if (qa_opt('moderate_notify_admin'))
qa_send_notification(null, qa_opt('feedback_email'), null, qa_lang('emails/moderate_subject'), qa_lang('emails/moderate_body'), array(
'^p_handle' => isset($handle) ? $handle : qa_lang('main/anonymous'),
'^p_context' => $params['text'],
'^url' => qa_q_path($params['parentid'], $params['parent']['title'], true, 'A', $params['postid']),
));
qa_send_notification(null, qa_opt('feedback_email'), null,
($event=='a_requeue') ? qa_lang('emails/remoderate_subject') : qa_lang('emails/moderate_subject'),
($event=='a_requeue') ? qa_lang('emails/remoderate_body') : qa_lang('emails/moderate_body'),
array(
'^p_handle' => isset($handle) ? $handle : (strlen($params['name']) ? $params['name'] :
(strlen(@$oldanswer['name']) ? $oldanswer['name'] : qa_lang('main/anonymous'))),
'^p_context' => $params['text'],
'^url' => qa_q_path($params['parentid'], $params['parent']['title'], true, 'A', $params['postid']),
'^a_url' => qa_path_absolute('admin/moderate'),
)
);
break;
case 'c_queue':
case 'c_requeue':
if (qa_opt('moderate_notify_admin'))
qa_send_notification(null, qa_opt('feedback_email'), null, qa_lang('emails/moderate_subject'), qa_lang('emails/moderate_body'), array(
'^p_handle' => isset($handle) ? $handle : qa_lang('main/anonymous'),
'^p_context' => $params['text'],
'^url' => qa_q_path($params['questionid'], $params['question']['title'], true, 'C', $params['postid']),
));
qa_send_notification(null, qa_opt('feedback_email'), null,
($event=='c_requeue') ? qa_lang('emails/remoderate_subject') : qa_lang('emails/moderate_subject'),
($event=='c_requeue') ? qa_lang('emails/remoderate_body') : qa_lang('emails/moderate_body'),
array(
'^p_handle' => isset($handle) ? $handle : (strlen($params['name']) ? $params['name'] :
(strlen(@$oldcomment['name']) ? $oldcomment['name'] : // could also be after answer converted to comment
(strlen(@$oldanswer['name']) ? $oldanswer['name'] : qa_lang('main/anonymous')))),
'^p_context' => $params['text'],
'^url' => qa_q_path($params['questionid'], $params['question']['title'], true, 'C', $params['postid']),
'^a_url' => qa_path_absolute('admin/moderate'),
)
);
break;
......@@ -190,10 +213,12 @@
if ( ($notifycount>=0) && (($notifycount % qa_opt('flagging_notify_every'))==0) )
qa_send_notification(null, qa_opt('feedback_email'), null, qa_lang('emails/flagged_subject'), qa_lang('emails/flagged_body'), array(
'^p_handle' => isset($oldpost['handle']) ? $oldpost['handle'] : qa_lang('main/anonymous'),
'^p_handle' => isset($oldpost['handle']) ? $oldpost['handle'] :
(strlen($oldpost['name']) ? $oldpost['name'] : qa_lang('main/anonymous')),
'^flags' => ($flagcount==1) ? qa_lang_html_sub('main/1_flag', '1', '1') : qa_lang_html_sub('main/x_flags', $flagcount),
'^p_context' => trim(@$oldpost['title']."\n\n".qa_viewer_text($oldpost['content'], $oldpost['format'])),
'^url' => qa_q_path($params['questionid'], $params['question']['title'], true, $oldpost['basetype'], $oldpost['postid']),
'^a_url' => qa_path_absolute('admin/flagged'),
));
break;
......@@ -213,6 +238,32 @@
));
}
break;
case 'u_register':
if (qa_opt('register_notify_admin'))
qa_send_notification(null, qa_opt('feedback_email'), null, qa_lang('emails/u_registered_subject'),
qa_opt('moderate_users') ? qa_lang('emails/u_to_approve_body') : qa_lang('emails/u_registered_body'), array(
'^u_handle' => $handle,
'^url' => qa_path_absolute('user/'.$handle),
'^a_url' => qa_path_absolute('admin/approve'),
));
break;
case 'u_level':
if ( ($params['level']>=QA_USER_LEVEL_APPROVED) && ($params['oldlevel']<QA_USER_LEVEL_APPROVED) )
qa_send_notification($params['userid'], null, $params['handle'], qa_lang('emails/u_approved_subject'), qa_lang('emails/u_approved_body'), array(
'^url' => qa_path_absolute('user/'.$params['handle']),
));
break;
case 'u_wall_post':
if ($userid!=$params['userid'])
qa_send_notification($params['userid'], null, $params['handle'], qa_lang('emails/wall_post_subject'), qa_lang('emails/wall_post_body'), array(
'^f_handle' => isset($handle) ? $handle : qa_lang('main/anonymous'),
'^post' => $params['text'],
'^url' => qa_path_absolute('user/'.$params['handle'], null, 'wall'),
));
break;
}
}
......
......@@ -34,10 +34,12 @@
function process_event($event, $userid, $handle, $cookieid, $params)
{
if (@$params['silent']) // don't create updates about silent edits, and possibly other silent events in future
return;
require_once QA_INCLUDE_DIR.'qa-db-events.php';
require_once QA_INCLUDE_DIR.'qa-app-events.php';
switch ($event) {
case 'q_post':
if (isset($params['parent'])) // question is following an answer
......@@ -55,8 +57,6 @@
case 'c_post':
qa_create_event_for_q_user($params['questionid'], $params['postid'], null, $userid, $params['parent']['userid']);
$keyuserids=array();
foreach ($params['thread'] as $comment) // previous comments in thread (but not author of parent again)
......@@ -64,8 +64,27 @@
$keyuserids[$comment['userid']]=true;
foreach ($keyuserids as $keyuserid => $dummy)
if ( ($keyuserid != $userid) && ($keyuserid != $params['parent']['userid']) )
qa_db_event_create_not_entity($keyuserid, $params['questionid'], $params['postid'], null, $userid);
if ($keyuserid != $userid)
qa_db_event_create_not_entity($keyuserid, $params['questionid'], $params['postid'], QA_UPDATE_FOLLOWS, $userid);
switch ($params['parent']['basetype'])
{
case 'Q':
$updatetype=QA_UPDATE_C_FOR_Q;
break;
case 'A':
$updatetype=QA_UPDATE_C_FOR_A;
break;
default:
$updatetype=null;
break;
}
qa_create_event_for_q_user($params['questionid'], $params['postid'], $updatetype, $userid,
@$keyuserids[$params['parent']['userid']] ? null : $params['parent']['userid']);
// give precedence to 'your comment followed' rather than 'your Q/A commented' if both are true
break;
......@@ -97,11 +116,17 @@
break;
case 'q_hide':
if (isset($params['oldquestion']['userid']))
qa_db_event_create_not_entity($params['oldquestion']['userid'], $params['postid'], $params['postid'], QA_UPDATE_VISIBLE, $userid);
break;
case 'q_reshow':
qa_create_event_for_q_user($params['postid'], $params['postid'], QA_UPDATE_VISIBLE, $userid, $params['oldquestion']['userid']);
break;
case 'q_move':
qa_create_event_for_q_user($params['postid'], $params['postid'], QA_UPDATE_CATEGORY, $userid, $params['oldquestion']['userid']);
qa_create_event_for_category($params['categoryid'], $params['postid'], QA_UPDATE_CATEGORY, $userid);
......@@ -114,6 +139,12 @@
break;
case 'a_hide':
if (isset($params['oldanswer']['userid']))
qa_db_event_create_not_entity($params['oldanswer']['userid'], $params['parentid'], $params['postid'], QA_UPDATE_VISIBLE, $userid);
break;
case 'a_reshow':
qa_create_event_for_q_user($params['parentid'], $params['postid'], QA_UPDATE_VISIBLE, $userid, $params['oldanswer']['userid']);
break;
......@@ -133,6 +164,12 @@
break;
case 'c_hide':
if (isset($params['oldcomment']['userid']))
qa_db_event_create_not_entity($params['oldcomment']['userid'], $params['questionid'], $params['postid'], QA_UPDATE_VISIBLE, $userid);
break;
case 'c_reshow':
qa_create_event_for_q_user($params['questionid'], $params['postid'], QA_UPDATE_VISIBLE, $userid, $params['oldcomment']['userid']);
break;
......
......@@ -69,7 +69,7 @@
{
$countslugs=@count($categoryslugs);
@list($questions1, $questions2, $questions3, $questions4, $categories, $categoryid)=qa_db_select_with_pending(
list($questions1, $questions2, $questions3, $questions4, $categories, $categoryid)=qa_db_select_with_pending(
$questionselectspec1,
$questionselectspec2,
$questionselectspec3,
......@@ -292,8 +292,8 @@
$lines[]='<rss version="2.0">';
$lines[]='<channel>';
$lines[]='<title>'.qa_html($sitetitle.' - '.$title).'</title>';
$lines[]='<link>'.qa_path_html($linkrequest, $linkparams, $siteurl).'</link>';
$lines[]='<title>'.qa_xml($sitetitle.' - '.$title).'</title>';
$lines[]='<link>'.qa_xml(qa_path($linkrequest, $linkparams, $siteurl)).'</link>';
$lines[]='<description>Powered by Question2Answer</description>';
foreach ($questions as $question) {
......@@ -320,7 +320,7 @@
if ($feedtype=='search') {
$titleprefix='';
$urlhtml=qa_html($question['url']);
$urlxml=qa_xml($question['url']);
} else {
switch (@$question['obasetype'].'-'.@$question['oupdatetype']) {
......@@ -386,7 +386,7 @@
$titleprefix=isset($langstring) ? qa_lang($langstring) : '';
$urlhtml=qa_q_path_html($question['postid'], $question['title'], true, @$question['obasetype'], @$question['opostid']) ;
$urlxml=qa_xml(qa_q_path($question['postid'], $question['title'], true, @$question['obasetype'], @$question['opostid']));
}
if (isset($blockwordspreg))
......@@ -395,19 +395,19 @@
// Build the inner XML structure for each item
$lines[]='<item>';
$lines[]='<title>'.qa_html($titleprefix.$question['title']).'</title>';
$lines[]='<link>'.$urlhtml.'</link>';
$lines[]='<title>'.qa_xml($titleprefix.$question['title']).'</title>';
$lines[]='<link>'.$urlxml.'</link>';
if (isset($htmlcontent))
$lines[]='<description>'.qa_html($htmlcontent).'</description>'; // qa_html() a second time to put HTML code inside XML wrapper
$lines[]='<description>'.qa_xml($htmlcontent).'</description>';
if (isset($question['categoryname']))
$lines[]='<category>'.qa_html($question['categoryname']).'</category>';
$lines[]='<category>'.qa_xml($question['categoryname']).'</category>';
$lines[]='<guid isPermaLink="true">'.$urlhtml.'</guid>';
$lines[]='<guid isPermaLink="true">'.$urlxml.'</guid>';
if (isset($time))
$lines[]='<pubDate>'.qa_html(gmdate('r', $time)).'</pubDate>';
$lines[]='<pubDate>'.qa_xml(gmdate('r', $time)).'</pubDate>';
$lines[]='</item>';
}
......
......@@ -63,13 +63,13 @@
} else {
require_once QA_INCLUDE_DIR.'qa-app-options.php';
require_once QA_INCLUDE_DIR.'qa-db-blobs.php';
require_once QA_INCLUDE_DIR.'qa-app-blobs.php';
require_once QA_INCLUDE_DIR.'qa-util-image.php';
// Otherwise retrieve the raw image and scale as appropriate
$blob=qa_db_blob_read($blobid);
$blob=qa_read_blob($blobid);
if (isset($blob)) {
if ($size>0)
......
......@@ -63,7 +63,7 @@
$relativedepth=count($requestparts);
// Workaround for fact that Apache unescapes characters while rewriting, based on assumption that $_GET['qa-rewrite'] has
// right path depth, which is true do long as there are only escaped characters in the last part of the path
// right path depth, which is true so long as there are only escaped characters in the last part of the path
if (!empty($_SERVER['REQUEST_URI'])) {
$origpath=$_SERVER['REQUEST_URI'];
$_GET=array();
......@@ -73,8 +73,10 @@
$params=explode('&', substr($origpath, $questionpos+1));
foreach ($params as $param)
if (preg_match('/^([^\=]*)(\=(.*))?$/', $param, $matches))
$_GET[urldecode($matches[1])]=qa_string_to_gpc(urldecode(@$matches[3]));
if (preg_match('/^([^\=]*)(\=(.*))?$/', $param, $matches)) {
$argument=strtr(urldecode($matches[1]), '.', '_'); // simulate PHP's $_GET behavior
$_GET[$argument]=qa_string_to_gpc(urldecode(@$matches[3]));
}
$origpath=substr($origpath, 0, $questionpos);
}
......
......@@ -97,11 +97,9 @@
global $pass_failure_from_install;
if (@$pass_failure_from_install)
$errorhtml.="Question2Answer was unable to perform the installation query below. Please check the user in the config file has CREATE and ALTER permissions:\n\n";
$errorhtml.="Question2Answer was unable to perform the installation query below. Please check the user in the config file has CREATE and ALTER permissions:\n\n".qa_html($pass_failure_query."\n\nError ".$pass_failure_errno.": ".$pass_failure_error."\n\n");
else
$errorhtml.="Question2Answer query failed:\n\n";
$errorhtml.=qa_html($pass_failure_query."\n\nError ".$pass_failure_errno.": ".$pass_failure_error."\n\n");
$errorhtml.="A Question2Answer database query failed when generating this page.\n\nA full description of the failure is available in the web server's error log file.";
break;
}
......
......@@ -44,6 +44,15 @@
'moderate_title' => 'Moderate',
'basic_editor' => 'Basic Editor',
'before_main_menu' => 'Before tabs at top',
'blobs_directory_error' => 'The directory ^ defined as QA_BLOBS_DIRECTORY is not writable by the web server.',
'blobs_move_complete' => 'Migration of uploaded images and documents completed.',
'blobs_move_moved' => 'Migration ^1 of ^2 uploaded images and documents',
'blobs_stop' => 'Stop migrating',
'blobs_to_db' => 'Blobs to database',
'blobs_to_db_note' => '- migrate all uploaded images and documents from disk files to the database',
'blobs_to_disk' => 'Blobs to disk',
'blobs_to_disk_note' => '- migrate all uploaded images and documents from the database to disk files',
'block_button' => 'block',
'block_ips_note' => 'Use a hyphen for ranges or * to match any number. Examples: 192.168.0.4 , 192.168.0.0-192.168.0.31 , 192.168.0.*',
'block_words_note' => 'Use a * to match any letters. Examples: doh (will only match exact word doh) , doh* (will match doh or dohno) , do*h (will match doh, dooh, dough).',
'cancel_mailing_button' => 'Cancel Mailing',
......@@ -104,6 +113,7 @@
'field_type' => 'Content type:',
'first' => 'First',
'flagged_title' => 'Flagged',
'form_security_expired' => 'Form security code expired - please try again',
'from_anon' => 'From anonymous:',
'from_users' => 'From users:',
'general_title' => 'General',
......@@ -112,7 +122,6 @@
'hidden_questions_deleted' => 'Deleted ^1 of ^2 hidden questions without dependents...',
'hotness_factors' => 'Relative importance for question hotness:',
'hidden_title' => 'Hidden',
'installed_plugins' => 'Installed plugins:',
'ip_address_pages' => 'IP address pages',
'layout_title' => 'Layout',
'link_name' => 'Text of link:',
......@@ -126,6 +135,7 @@
'mailing_unsubscribe' => 'An unsubscribe link will be added at the bottom of every message.',
'maintenance_admin_only' => 'Your site is in ^1maintenance^2 and is currently inaccessible to regular users.',
'maximum_x' => ' (max ^)',
'approve_users_title' => 'Approve users',
'module_x_database_init' => 'The ^1 ^2 module requires some ^3database initialization^4.',
'most_flagged_title' => 'Flagged content',
'mysql_version' => 'MySQL version:',
......@@ -139,8 +149,8 @@
'no_image_gd' => 'The installed version of PHP was compiled without GD image support, so users cannot upload their avatars directly.',
'no_link' => 'No link',
'no_multibyte' => 'The installed version of PHP was compiled without multibyte string support. Searching will be less effective for non-Roman characters.',
'no_plugin_options' => 'None of your installed plugins have options to display.',
'no_privileges' => 'Only administrators may access this page.',
'no_unapproved_found' => 'No users waiting for approval',
'not_logged_in' => 'Please ^1log in^2 as the administrator to access this page.',
'opposite_main_menu' => 'Far end of tabs at top',
'options_reset' => 'Options reset',
......@@ -170,7 +180,7 @@
'points' => 'points',
'position' => 'Position:',
'posting_title' => 'Posting',
'profile_fields' => 'Extra fields on user profile:',
'profile_fields' => 'Extra fields for users:',
'q2a_build_date' => 'Build date:',
'q2a_db_size' => 'Database size:',
'q2a_db_version' => 'Q2A database version:',
......@@ -218,6 +228,7 @@
'save_recalc_button' => 'Save and Recalculate',
'send_test_button' => 'Send Test to Me',
'show_defaults_button' => 'Show Defaults',
'show_on_register_form' => 'Show field on user registration form',
'slug_bad_chars' => 'The slug may not contain these characters: ^',
'slug_reserved' => 'This slug is reserved for use by another page',
'spam_title' => 'Spam',
......
......@@ -43,10 +43,10 @@
'feedback_body' => "Comments:\n^message\n\nName:\n^name\n\nEmail:\n^email\n\nPrevious page:\n^previous\n\nUser:\n^url\n\nIP address:\n^ip\n\nBrowser:\n^browser",
'feedback_subject' => '^ feedback',
'flagged_body' => "A post by ^p_handle has received ^flags:\n\n^open^p_context^close\n\nClick below to see the post:\n\n^url\n\nThank you,\n\n^site_title",
'flagged_body' => "A post by ^p_handle has received ^flags:\n\n^open^p_context^close\n\nClick below to see the post:\n\n^url\n\n\nClick below to review all flagged posts:\n\n^a_url\n\n\nThank you,\n\n^site_title",
'flagged_subject' => '^site_title has a flagged post',
'moderate_body' => "A post by ^p_handle requires your approval:\n\n^open^p_context^close\n\nClick below to approve or reject the post:\n\n^url\n\nThank you,\n\n^site_title",
'moderate_body' => "A post by ^p_handle requires your approval:\n\n^open^p_context^close\n\nClick below to approve or reject the post:\n\n^url\n\n\nClick below to review all queued posts:\n\n^a_url\n\n\nThank you,\n\n^site_title",
'moderate_subject' => '^site_title moderation',
'new_password_body' => "Your new password for ^site_title is below.\n\nPassword: ^password\n\nIt is recommended to change this password immediately after logging in.\n\nThank you,\n^site_title\n^url",
......@@ -65,11 +65,24 @@
'q_posted_body' => "A new question has been asked by ^q_handle:\n\n^open^q_title\n\n^q_content^close\n\nClick below to see the question:\n\n^url\n\nThank you,\n\n^site_title",
'q_posted_subject' => '^site_title has a new question',
'remoderate_body' => "An edited post by ^p_handle requires your reapproval:\n\n^open^p_context^close\n\nClick below to approve or hide the edited post:\n\n^url\n\n\nClick below to review all queued posts:\n\n^a_url\n\n\nThank you,\n\n^site_title",
'remoderate_subject' => '^site_title moderation',
'reset_body' => "Please click below to reset your password for ^site_title.\n\n^url\n\nAlternatively, enter the code below into the field provided.\n\nCode: ^code\n\nIf you did not ask to reset your password, please ignore this message.\n\nThank you,\n^site_title",
'reset_subject' => '^site_title - Reset Forgotten Password',
'to_handle_prefix' => "^,\n\n",
'u_registered_body' => "A new user has registered as ^u_handle.\n\nClick below to view the user profile:\n\n^url\n\nThank you,\n\n^site_title",
'u_to_approve_body' => "A new user has registered as ^u_handle.\n\nClick below to approve the user:\n\n^url\n\nClick below to review all users waiting for approval:\n\n^a_url\n\nThank you,\n\n^site_title",
'u_registered_subject' => '^site_title has a new registered user',
'u_approved_body' => "You can see your new user profile here:\n\n^url\n\nThank you,\n\n^site_title",
'u_approved_subject' => 'Your ^site_title user has been approved',
'wall_post_subject' => 'Post on your ^site_title wall',
'wall_post_body' => "^f_handle has posted on your user wall at ^site_title:\n\n^open^post^close\n\nYou may respond to the post here:\n\n^url\n\nThank you,\n\n^site_title",
'welcome_body' => "Thank you for registering for ^site_title.\n\n^custom^confirmYour login details are as follows:\n\nEmail: ^email\nPassword: ^password\n\nPlease keep this information safe for future reference.\n\nThank you,\n\n^site_title\n^url",
'welcome_confirm' => "Please click below to confirm your email address.\n\n^url\n\n",
......
......@@ -178,11 +178,14 @@
'unupvoteda_qs_in_x' => 'Questions without an upvoted answer in ^',
'unupvoteda_qs_title' => 'Recent questions without an upvoted answer',
'upload_limit' => 'Too many uploads - please try again in an hour',
'view_q_must_be_approved' => 'Your account must be approved to view question pages.',
'view_q_must_confirm' => 'Please ^5confirm your email address^6 to view question pages.',
'view_q_must_login' => 'Please ^1log in^2 or ^3register^4 to view question pages.',
'viewed_qs_in_x' => 'Most viewed questions in ^',
'viewed_qs_title' => 'Most viewed questions',
'vote_disabled_approve' => 'You account must be approved before you can vote',
'vote_disabled_down' => 'Voting down is only available to some users',
'vote_disabled_down_approve' => 'Your account must be approved before you can vote down',
'vote_disabled_hidden_a' => 'You cannot vote on hidden answers',
'vote_disabled_hidden_q' => 'You cannot vote on hidden questions',
'vote_disabled_level' => 'Voting is only available to some users',
......@@ -200,6 +203,7 @@
'voted_qs_in_x' => 'Highest voted questions in ^',
'voted_qs_title' => 'Highest voted questions',
'voted_up_popup' => 'You have voted this up - click to remove vote',
'written' => '', // blank in English - placeholder for other languages
'x_ago' => '^ ago',
'x_answers' => '^ answers',
'x_comments' => '^ comments',
......
......@@ -27,6 +27,7 @@
return array(
'block_ip_button' => 'Block IP address',
'browse_categories' => 'Browse categories',
'captcha_approve_fix' => 'This verification will stop appearing once your account is approved.',
'captcha_confirm_fix' => 'To avoid this verification in future, please ^5confirm your email address^6.',
'captcha_error' => 'Please complete the anti-spam verification',
'captcha_label' => 'Anti-spam verification:',
......@@ -53,6 +54,8 @@
'feedback_name' => 'Your name: (optional)',
'feedback_sent' => 'Your message below was sent - thank you.',
'feedback_title' => 'Send feedback',
'form_security_again' => 'Please click again to confirm',
'form_security_reload' => 'Please reload the page then try again',
'hide_all_ip_button' => 'Hide all posts from this IP',
'host_name' => 'Host name:',
'matches_blocked_ips' => 'Matches blocked IP addresses:',
......@@ -61,15 +64,16 @@
'message_for_x' => 'Your message for ^:',
'message_limit' => 'Too many private messages sent - please try again in an hour',
'message_must_login' => 'Please ^1log in^2 or ^3register^4 to send private messages.',
'message_received_x_ago' => 'Received ^ ago:',
'message_recent_history' => 'Recent correspondence with ^',
'message_sent_x_ago' => 'Sent ^ ago:',
'message_sent' => 'Your private message below was sent',
'my_favorites_title' => 'My favorites',
'nav_all_my_updates' => 'All my updates',
'nav_my_content' => 'My content',
'nav_my_details' => 'My details',
'nav_my_favorites' => 'My favorites',
'nav_user_activity' => 'Recent activity',
'nav_user_as' => 'All answers',
'nav_user_qs' => 'All questions',
'no_activity_from_x' => 'No activity from ^',
'no_favorite_categories' => 'No favorite categories',
'no_favorite_qs' => 'No favorite questions',
......@@ -87,6 +91,26 @@
'suggest_favorites_add' => 'To add a question or other item to your favorites, click the ^ at the top of its page.',
'suggest_update_favorites' => 'For more updates, add items to ^1your favorites^2.',
'unblock_ip_button' => 'Unblock IP address',
'your_a_commented' => 'your answer commented',
'your_a_edited' => 'your answer edited',
'your_a_hidden' => 'your answer hidden',
'your_a_questioned' => 'asked on your answer',
'your_a_reshown' => 'your answer reshown',
'your_a_selected' => 'your answer selected',
'your_c_edited' => 'your comment edited',
'your_c_followed' => 'your comment followed',
'your_c_hidden' => 'your comment hidden',
'your_c_moved' => 'your comment moved',
'your_c_reshown' => 'your comment reshown',
'your_q_answered' => 'your question answered',
'your_q_closed' => 'your question closed',
'your_q_commented' => 'your question commented',
'your_q_edited' => 'your question edited',
'your_q_hidden' => 'your question hidden',
'your_q_recategorized' => 'your question recategorized',
'your_q_reopened' => 'your question reopened',
'your_q_reshown' => 'your question reshown',
'your_q_retagged' => 'your question retagged',
);
......
......@@ -25,6 +25,7 @@
*/
return array(
'allow_anon_name' => 'Request a name for anonymous posts:',
'allow_change_usernames' => 'Allow users with posts to change their username:',
'allow_close_questions' => 'Allow questions to be manually closed:',
'allow_login_email_only' => 'Only log in by email address (not username):',
......@@ -32,11 +33,14 @@
'allow_no_category' => 'Allow questions with no category',
'allow_no_sub_category' => 'Allow questions with a category but no sub-category',
'allow_private_messages' => 'Enable private messaging between users:',
'allow_user_walls' => 'Enable wall posts on user profiles:',
'allow_self_answer' => 'Allow users to answer their own question:',
'allow_view_q_bots' => 'Allow search engines to view question pages',
'approve_user_required' => 'All new users must be approved:',
'avatar_allow_gravatar' => 'Allow ^1Gravatar^2 avatars:',
'avatar_allow_upload' => 'Allow users to upload avatars:',
'avatar_default_show' => 'Default avatar:',
'avatar_message_list_size' => 'Avatar size on message lists:',
'avatar_profile_size' => 'Avatar size on user profile page:',
'avatar_q_list_size' => 'Avatar size on question lists:',
'avatar_q_page_a_size' => 'Avatar size on answers:',
......@@ -51,13 +55,14 @@
'captcha_on_feedback' => 'Use captcha on feedback form:',
'captcha_on_register' => 'Use captcha for user registration:',
'captcha_on_reset_password' => 'Use captcha on reset password form:',
'captcha_on_unapproved' => 'Use captcha if user not yet approved:',
'captcha_on_unconfirmed' => 'Use captcha if email not confirmed:',
'columns_tags' => 'Columns on Tags page:',
'columns_users' => 'Columns on Users page:',
'comment_on_as' => 'Allow comments on answers:',
'comment_on_qs' => 'Allow comments on questions:',
'confirm_user_emails' => 'Request confirmation of user emails:',
'confirm_user_required' => 'New users must complete confirmation:',
'confirm_user_required' => 'All new users must confirm their email:',
'custom_home_content' => 'Home page content - HTML allowed:',
'custom_home_heading' => 'Home page heading:',
'default_privacy' => 'Privacy: Your email address will not be shared or sold to third parties.',
......@@ -124,7 +129,7 @@
'max_rate_ip_cs' => 'Rate limit for posting comments:',
'max_rate_ip_flags' => 'Rate limit for flagging posts:',
'max_rate_ip_logins' => 'Rate limit for logging in:',
'max_rate_ip_messages' => 'Rate limit for sending private messages:',
'max_rate_ip_messages' => 'Rate limit for private and wall messages:',
'max_rate_ip_qs' => 'Rate limit for asking questions:',
'max_rate_ip_registers' => 'Rate limit for user registrations:',
'max_rate_ip_uploads' => 'Rate limit for uploading files:',
......@@ -143,9 +148,13 @@
'min_num_q_tags' => 'Minimum number of tags:',
'moderate_anon_post' => 'Use moderation for anonymous posts:',
'moderate_by_points' => 'Use moderation for users with few points:',
'moderate_edited_again' => 'Re-moderate posts after editing:',
'moderate_notify_admin' => 'Email me when a post needs moderation:',
'moderate_points_limit' => 'Use moderation for users with less than:',
'moderate_unapproved' => 'Use moderation if user not yet approved:',
'moderate_unconfirmed' => 'Use moderation if email not confirmed:',
'moderate_update_time' => 'Time to show on moderated posts:',
'moderate_users' => 'Enable moderation (approval) of users:',
'neat_urls' => 'URL structure:',
'notify_admin_q_post' => 'Email this address when a question is posted',
'notify_users_default' => 'Check email notification box by default:',
......@@ -162,11 +171,13 @@
'page_size_tag_qs' => 'Questions on each tag page:',
'page_size_tags' => 'Length of Tags page:',
'page_size_una_qs' => 'Length of Unanswered page:',
'page_size_user_posts' => 'Posts on each user page:',
'page_size_users' => 'Length of Users page:',
'pages_prev_next' => 'Links to previous/next pages:',
'permit_admins' => 'Administrators',
'permit_all' => 'Anybody',
'permit_approve_users' => 'Approving registered users:',
'permit_approved' => 'Approved users only',
'permit_approved_points' => 'Approved users with enough points',
'permit_block' => 'Blocking or unblocking user or IPs:',
'permit_confirmed' => 'Registered users with email confirmed',
'permit_create_admins' => 'Creating administrators:',
......@@ -213,6 +224,7 @@
'points_vote_up_q' => 'Voting up a question:',
'q_urls_remove_accents' => 'Remove accents from question URLs:',
'q_urls_title_length' => 'Question title length in URLs:',
'register_notify_admin' => 'Email me when a new user registers:',
'search_module' => 'Use search module:',
'show_a_form_immediate' => 'Show answer form immediately:',
'show_always' => 'Always',
......@@ -242,6 +254,7 @@
'show_user_points' => 'Show points next to usernames:',
'show_user_titles' => 'Show titles next to usernames:',
'show_view_counts' => 'Show view count in question lists:',
'show_view_count_q_page' => 'Show view count on question pages:',
'show_when_created' => 'Show age of user posts:',
'site_language' => 'Site language:',
'site_maintenance' => 'Take site down for temporary maintenance',
......@@ -263,6 +276,8 @@
'suspend_register_users' => 'Temporarily suspend new user registrations:',
'tag_separator_comma' => 'Use comma as the only tag separator:',
'tags_or_categories' => 'Question classification:',
'time_approved' => 'Time approved',
'time_written' => 'Time written',
'votes_separated' => 'Show separate up and down votes:',
'voting_on_as' => 'Allow voting on answers:',
'voting_on_q_page_only' => 'Allow voting on question page only:',
......
......@@ -31,32 +31,48 @@
'1_with_best_chosen' => ' (1 with best answer chosen)',
'activity_by_x' => 'Activity by ^',
'answers' => 'Answers:',
'answers_by_x' => 'Answers by ^',
'bonus_points' => 'Bonus points:',
'comments' => 'Comments:',
'delete_wall_post_popup' => 'Delete this wall post',
'extra_privileges' => 'Extra privileges:',
'gave_out' => 'Gave out:',
'wall_for_x' => 'Wall for ^',
'my_account_title' => 'My account details',
'no_answers_by_x' => 'No answers by ^',
'no_posts_by_x' => 'No posts by ^',
'no_questions_by_x' => 'No questions by ^',
'permit_anon_view_ips' => 'Viewing IPs of anonymous posts',
'permit_close_q' => 'Closing any question',
'permit_delete_hidden' => 'Deleting hidden posts',
'permit_edit_a' => 'Editing any answer',
'permit_edit_c' => 'Editing any comment',
'permit_edit_q' => 'Editing any question',
'permit_edit_silent' => 'Editing posts silently',
'permit_flag' => 'Flagging posts',
'permit_hide_show' => 'Hiding or showing any post',
'permit_moderate' => 'Approving or rejecting posts',
'permit_post_a' => 'Answering questions',
'permit_post_c' => 'Adding comments',
'permit_post_q' => 'Asking questions',
'permit_post_wall' => 'Posting on user walls',
'permit_recat' => 'Recategorizing any question',
'permit_retag' => 'Retagging any question',
'permit_select_a' => 'Selecting answer for any question',
'permit_view_q_page' => 'Viewing question pages',
'permit_view_voters_flaggers' => 'Viewing who voted or flagged posts',
'permit_vote_a' => 'Voting on answers',
'permit_vote_down' => 'Voting posts down',
'permit_vote_q' => 'Voting on questions',
'post_wall_button' => 'Add wall post',
'post_wall_blocked' => 'This user has disallowed new posts on their wall',
'post_wall_empty' => 'Please enter something to post on this wall',
'post_wall_limit' => 'Too many wall posts created - please try again in an hour',
'post_wall_must_be_approved' => 'Your account must be approved to post on this wall.',
'post_wall_must_login' => 'Please ^1log in^2 or ^3register^4 to post on this wall.',
'post_wall_must_confirm' => 'Please ^5confirm your email address^6 to post on this wall.',
'questions' => 'Questions:',
'questions_by_x' => 'Questions by ^',
'ranked_x' => ' (ranked #^)',
'received' => 'Received:',
'recent_activity_by_x' => 'Recent activity by ^',
......
......@@ -38,8 +38,10 @@
'add_answer_button' => 'Add answer',
'add_comment_button' => 'Add comment',
'add_q_favorites' => 'Add this question to my favorites',
'anon_name_label' => 'Your name to display (optional):',
'answer_button' => 'answer',
'answer_limit' => 'Too many answers received - please try again in an hour',
'answer_must_be_approved' => 'Your account must be approved before you answer a question.',
'answer_must_confirm' => 'Please ^5confirm your email address^6 to answer this question.',
'answer_must_login' => 'Please ^1log in^2 or ^3register^4 to answer this question.',
'answer_q_popup' => 'Answer this question',
......@@ -48,6 +50,7 @@
'ask_follow_from_a' => 'Your question will be related to this answer:',
'ask_follow_title' => 'Ask a related question',
'ask_limit' => 'Too many questions received - please try again in an hour',
'ask_must_be_approved' => 'Your account must be approved before you ask a question.',
'ask_must_confirm' => 'Please ^5confirm your email address^6 to ask a question.',
'ask_must_login' => 'Please ^1log in^2 or ^3register^4 to ask a question.',
'ask_same_q' => 'Before proceeding, please check your question was not asked already:',
......@@ -59,6 +62,7 @@
'c_your_waiting_approval' => 'Your comment will be checked and approved shortly.',
'category_js_note' => 'To select any category, please enable Javascript in your web browser.',
'category_required' => 'Please choose a category',
'category_ask_not_allowed' => 'You do not have permission to ask questions in this category',
'claim_button' => 'I wrote this',
'clear_flags_button' => 'clear flags',
'clear_flags_popup' => 'Remove flags by all users',
......@@ -76,6 +80,7 @@
'comment_a_popup' => 'Add a comment on this answer',
'comment_button' => 'comment',
'comment_limit' => 'Too many comments received - please try again in an hour',
'comment_must_be_approved' => 'Your account must be approved before you add a comment.',
'comment_must_confirm' => 'Please ^5confirm your email address^6 to add a comment.',
'comment_must_login' => 'Please ^1log in^2 or ^3register^4 to add a comment.',
'comment_on_a' => 'On answer: ',
......@@ -144,6 +149,7 @@
'retag_cat_popup' => 'Change this question\'s category or tags',
'retag_popup' => 'Change this question\'s tags',
'retag_q_title' => 'Retag question',
'save_silent_label' => 'Save silently to hide that this was edited',
'select_popup' => 'Click to select as best answer',
'select_text' => 'Best answer',
'show_1_comment' => 'Show 1 comment',
......
......@@ -27,12 +27,19 @@
return array(
'about' => 'About',
'add_user_x_favorites' => 'Add user ^ to my favorites',
'approve_required' => 'Please wait for your account to be approved or ^1add more information^2.',
'approve_title' => 'User approval pending',
'approve_user_button' => 'Approve User',
'approved_user' => 'Approved user',
'avatar_default' => 'Default',
'avatar_gravatar' => 'Show my ^1Gravatar^2',
'avatar_label' => 'Avatar:',
'avatar_none' => 'None',
'block_user_button' => 'Block User',
'blocked_users' => 'Blocked users',
'category_level_add' => ' - ^1add per-category type^2',
'category_level_in' => 'in the category below:',
'category_level_label' => 'Per-category type:',
'change_email_link' => ' - ^1change email^2',
'change_password' => 'Change Password',
'confirm_complete' => 'Thank you - your email address has been confirmed',
......@@ -42,7 +49,7 @@
'confirm_wrong_log_in' => 'Code not correct - please ^1log in^2 to send a new link',
'confirm_wrong_resend' => 'Code not correct - please click below to send a new link',
'delete_user_button' => 'Delete User',
'edit_user_button' => 'Edit this User',
'edit_user_button' => 'Edit User',
'email_confirmed' => 'Confirmed',
'email_exists' => 'Email already belongs to an account',
'email_handle_label' => 'Email or Username:',
......@@ -63,6 +70,8 @@
'level_admin' => 'Administrator',
'level_editor' => 'Editor',
'level_expert' => 'Expert',
'level_for_category' => '^1 for ^2',
'level_in_general' => 'in general',
'level_moderator' => 'Moderator',
'level_super' => 'Super Administrator',
'location' => 'Location',
......@@ -80,7 +89,9 @@
'no_permission' => 'You do not have permission to perform this operation',
'old_password' => 'Old password:',
'only_shown_admins' => '(only shown to admins)',
'only_shown_moderators' => '(only shown to moderators)',
'only_shown_editors' => '(only shown to editors and above)',
'only_shown_experts' => '(only shown to experts and above)',
'only_shown_moderators' => '(only shown to moderators and admins)',
'password_changed' => 'Password changed',
'password_label' => 'Password:',
'password_min' => 'Password must be at least ^ characters',
......@@ -89,13 +100,16 @@
'password_sent' => 'Your new password was emailed to you',
'password_to_set' => 'Please set on your account page',
'password_wrong' => 'Password not correct',
'private_messages_explanation' => 'Allow users to email me (without seeing my address)',
'private_messages_explanation' => 'Allow users to email you (without seeing your address)',
'private_messages' => 'Private messages:',
'profile_saved' => 'Profile saved',
'wall_posts' => 'Wall posts:',
'wall_posts_explanation' => 'Allow users to post on your wall (you will also be emailed)',
'register_button' => 'Register',
'register_limit' => 'Too many registrations - please try again in an hour',
'register_suspended' => 'Registration of new users has been temporarily suspended. Please try again soon.',
'register_title' => 'Register as a new user',
'registered_label' => 'Registered:',
'registered_user' => 'Registered user',
'remember_label' => 'Remember me on this computer',
'remember' => 'Remember',
......
<?php
/*
Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/
File: qa-include/qa-layer-voters-flaggers.php
Version: See define()s at top of qa-include/qa-base.php
Description: Theme layer class for viewing voters and flaggers
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
More about this license: http://www.question2answer.org/license.php
*/
class qa_html_theme_layer extends qa_html_theme_base {
var $qa_voters_flaggers_queue=array();
var $qa_voters_flaggers_cache=array();
// Utility functions for this layer
function queue_post_voters_flaggers($post)
{
if (!qa_user_post_permit_error('permit_view_voters_flaggers', $post)) {
$postids=array(@$post['postid'], @$post['opostid']); // opostid can be relevant for flags
foreach ($postids as $postid)
if (isset($postid) && !isset($this->qa_voters_flaggers_cache[$postid]))
$this->qa_voters_flaggers_queue[$postid]=true;
}
}
function queue_raw_posts_voters_flaggers($posts)
{
if (is_array($posts))
foreach ($posts as $post)
if (isset($post['raw']))
$this->queue_post_voters_flaggers($post['raw']);
}
function retrieve_queued_voters_flaggers()
{
if (count($this->qa_voters_flaggers_queue)) {
require_once QA_INCLUDE_DIR.'qa-db-votes.php';
$postids=array_keys($this->qa_voters_flaggers_queue);
foreach ($postids as $postid)
$this->qa_voters_flaggers_cache[$postid]=array();
$newvotersflaggers=qa_db_uservoteflag_posts_get($postids);
if (QA_FINAL_EXTERNAL_USERS) {
$keyuserids=array();
foreach ($newvotersflaggers as $voterflagger)
$keyuserids[$voterflagger['userid']]=true;
$useridhandles=qa_get_public_from_userids(array_keys($keyuserids));
foreach ($newvotersflaggers as $index => $voterflagger)
$newvotersflaggers[$index]['handle']=@$useridhandles[$voterflagger['userid']];
}
foreach ($newvotersflaggers as $voterflagger)
$this->qa_voters_flaggers_cache[$voterflagger['postid']][]=$voterflagger;
$this->qa_voters_flaggers_queue=array();
}
}
function get_post_voters_flaggers($post, $postid)
{
require_once QA_INCLUDE_DIR.'qa-util-sort.php';
if (!isset($this->qa_voters_flaggers_cache[$postid])) {
$this->queue_post_voters_flaggers($post);
$this->retrieve_queued_voters_flaggers();
}
$votersflaggers=@$this->qa_voters_flaggers_cache[$postid];
if (isset($votersflaggers))
qa_sort_by($votersflaggers, 'handle');
return $votersflaggers;
}
// Collect up all required postids for the entire page to save DB queries - common case where whole page output
function main()
{
foreach ($this->content as $key => $part) {
if (strpos($key, 'q_list')===0)
$this->queue_raw_posts_voters_flaggers(@$part['qs']);
elseif (strpos($key, 'q_view')===0) {
$this->queue_post_voters_flaggers($part['raw']);
$this->queue_raw_posts_voters_flaggers($part['c_list']['cs']);
} elseif (strpos($key, 'a_list')===0) {
if (!empty($part)) {
$this->queue_raw_posts_voters_flaggers($part['as']);
foreach ($part['as'] as $a_item)
$this->queue_raw_posts_voters_flaggers(@$a_item['c_list']['cs']);
}
}
}
qa_html_theme_base::main();
}
// Other functions which also collect up required postids for lists to save DB queries - helps with widget output and Ajax calls
function q_list_items($q_items)
{
$this->queue_raw_posts_voters_flaggers($q_items);
qa_html_theme_base::q_list_items($q_items);
}
function a_list_items($a_items)
{
$this->queue_raw_posts_voters_flaggers($a_items);
qa_html_theme_base::a_list_items($a_items);
}
function c_list_items($c_items)
{
$this->queue_raw_posts_voters_flaggers($c_items);
qa_html_theme_base::c_list_items($c_items);
}
// Actual output of the voters and flaggers
function vote_count($post)
{
$votersflaggers=$this->get_post_voters_flaggers($post['raw'], $post['raw']['postid']);
$tooltip='';
if (isset($votersflaggers)) {
$uphandles='';
$downhandles='';
foreach ($votersflaggers as $voterflagger) {
if ($voterflagger['vote']>0)
$uphandles.=(strlen($uphandles) ? ', ' : '').qa_html($voterflagger['handle']);
if ($voterflagger['vote']<0)
$downhandles.=(strlen($downhandles) ? ', ' : '').qa_html($voterflagger['handle']);
$tooltip=trim((strlen($uphandles) ? ('&uarr; '.$uphandles) : '')."\n\n".(strlen($downhandles) ? ('&darr; '.$downhandles) : ''));
}
}
if (strlen($tooltip))
$this->output('<SPAN TITLE="'.$tooltip.'">');
qa_html_theme_base::vote_count($post);
if (strlen($tooltip))
$this->output('</SPAN>');
}
function post_meta_flags($post, $class)
{
$postid=@$post['raw']['opostid'];
if (!isset($postid))
$postid=@$post['raw']['postid'];
$tooltip='';
if (isset($postid)) {
$votersflaggers=$this->get_post_voters_flaggers($post, $postid);
if (isset($votersflaggers))
foreach ($votersflaggers as $voterflagger)
if ($voterflagger['flag']>0)
$tooltip.=(strlen($tooltip) ? ', ' : '').qa_html($voterflagger['handle']);
}
if (strlen($tooltip))
$this->output('<SPAN TITLE="&#9873; '.$tooltip.'">');
qa_html_theme_base::post_meta_flags($post, $class);
if (strlen($tooltip))
$this->output('</SPAN>');
}
}
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
......@@ -70,82 +70,91 @@
$inhandle=$changehandle ? qa_post_text('handle') : $useraccount['handle'];
$inemail=qa_post_text('email');
$inmessages=qa_post_text('messages');
$inwallposts=qa_post_text('wall');
$inmailings=qa_post_text('mailings');
$inavatar=qa_post_text('avatar');
$errors=qa_handle_email_filter($inhandle, $inemail, $useraccount);
if (!isset($errors['handle']))
qa_db_user_set($userid, 'handle', $inhandle);
if (!isset($errors['email']))
if ($inemail != $useraccount['email']) {
qa_db_user_set($userid, 'email', $inemail);
qa_db_user_set_flag($userid, QA_USER_FLAGS_EMAIL_CONFIRMED, false);
$isconfirmed=false;
if ($doconfirms)
qa_send_new_confirm($userid);
}
if (qa_opt('allow_private_messages'))
qa_db_user_set_flag($userid, QA_USER_FLAGS_NO_MESSAGES, !$inmessages);
$inprofile=array();
foreach ($userfields as $userfield)
$inprofile[$userfield['fieldid']]=qa_post_text('field_'.$userfield['fieldid']);
if (qa_opt('mailing_enabled'))
qa_db_user_set_flag($userid, QA_USER_FLAGS_NO_MAILINGS, !$inmailings);
if (!qa_check_form_security_code('account', qa_post_text('code')))
$errors['page']=qa_lang_html('misc/form_security_again');
qa_db_user_set_flag($userid, QA_USER_FLAGS_SHOW_AVATAR, ($inavatar=='uploaded'));
qa_db_user_set_flag($userid, QA_USER_FLAGS_SHOW_GRAVATAR, ($inavatar=='gravatar'));
if (is_array(@$_FILES['file']) && $_FILES['file']['size']) {
require_once QA_INCLUDE_DIR.'qa-app-limits.php';
else {
$errors=qa_handle_email_filter($inhandle, $inemail, $useraccount);
if (!isset($errors['handle']))
qa_db_user_set($userid, 'handle', $inhandle);
if (!isset($errors['email']))
if ($inemail != $useraccount['email']) {
qa_db_user_set($userid, 'email', $inemail);
qa_db_user_set_flag($userid, QA_USER_FLAGS_EMAIL_CONFIRMED, false);
$isconfirmed=false;
if ($doconfirms)
qa_send_new_confirm($userid);
}
if (qa_opt('allow_private_messages'))
qa_db_user_set_flag($userid, QA_USER_FLAGS_NO_MESSAGES, !$inmessages);
switch (qa_user_permit_error(null, QA_LIMIT_UPLOADS))
{
case 'limit':
$errors['avatar']=qa_lang('main/upload_limit');
break;
if (qa_opt('allow_user_walls'))
qa_db_user_set_flag($userid, QA_USER_FLAGS_NO_WALL_POSTS, !$inwallposts);
if (qa_opt('mailing_enabled'))
qa_db_user_set_flag($userid, QA_USER_FLAGS_NO_MAILINGS, !$inmailings);
qa_db_user_set_flag($userid, QA_USER_FLAGS_SHOW_AVATAR, ($inavatar=='uploaded'));
qa_db_user_set_flag($userid, QA_USER_FLAGS_SHOW_GRAVATAR, ($inavatar=='gravatar'));
if (is_array(@$_FILES['file']) && $_FILES['file']['size']) {
require_once QA_INCLUDE_DIR.'qa-app-limits.php';
default:
$errors['avatar']=qa_lang('users/no_permission');
break;
switch (qa_user_permit_error(null, QA_LIMIT_UPLOADS))
{
case 'limit':
$errors['avatar']=qa_lang('main/upload_limit');
break;
case false:
qa_limits_increment($userid, QA_LIMIT_UPLOADS);
$toobig=qa_image_file_too_big($_FILES['file']['tmp_name'], qa_opt('avatar_store_size'));
if ($toobig)
$errors['avatar']=qa_lang_sub('main/image_too_big_x_pc', (int)($toobig*100));
elseif (!qa_set_user_avatar($userid, file_get_contents($_FILES['file']['tmp_name']), $useraccount['avatarblobid']))
$errors['avatar']=qa_lang_sub('main/image_not_read', implode(', ', qa_gd_image_formats()));
break;
default:
$errors['avatar']=qa_lang('users/no_permission');
break;
case false:
qa_limits_increment($userid, QA_LIMIT_UPLOADS);
$toobig=qa_image_file_too_big($_FILES['file']['tmp_name'], qa_opt('avatar_store_size'));
if ($toobig)
$errors['avatar']=qa_lang_sub('main/image_too_big_x_pc', (int)($toobig*100));
elseif (!qa_set_user_avatar($userid, file_get_contents($_FILES['file']['tmp_name']), $useraccount['avatarblobid']))
$errors['avatar']=qa_lang_sub('main/image_not_read', implode(', ', qa_gd_image_formats()));
break;
}
}
}
$inprofile=array();
foreach ($userfields as $userfield)
$inprofile[$userfield['fieldid']]=qa_post_text('field_'.$userfield['fieldid']);
$filtermodules=qa_load_modules_with('filter', 'filter_profile');
foreach ($filtermodules as $filtermodule)
$filtermodule->filter_profile($inprofile, $errors, $useraccount, $userprofile);
foreach ($userfields as $userfield)
if (!isset($errors[$userfield['fieldid']]))
qa_db_user_profile_set($userid, $userfield['title'], $inprofile[$userfield['fieldid']]);
$filtermodules=qa_load_modules_with('filter', 'filter_profile');
foreach ($filtermodules as $filtermodule)
$filtermodule->filter_profile($inprofile, $errors, $useraccount, $userprofile);
list($useraccount, $userprofile)=qa_db_select_with_pending(
qa_db_user_account_selectspec($userid, true),
qa_db_user_profile_selectspec($userid, true)
);
qa_report_event('u_save', $userid, $useraccount['handle'], qa_cookie_get());
if (empty($errors))
qa_redirect('account', array('state' => 'profile-saved'));
qa_logged_in_user_flush();
foreach ($userfields as $userfield)
if (!isset($errors[$userfield['fieldid']]))
qa_db_user_profile_set($userid, $userfield['title'], $inprofile[$userfield['fieldid']]);
list($useraccount, $userprofile)=qa_db_select_with_pending(
qa_db_user_account_selectspec($userid, true),
qa_db_user_profile_selectspec($userid, true)
);
qa_report_event('u_save', $userid, $useraccount['handle'], qa_cookie_get());
if (empty($errors))
qa_redirect('account', array('state' => 'profile-saved'));
qa_logged_in_user_flush();
}
}
......@@ -158,25 +167,30 @@
$innewpassword1=qa_post_text('newpassword1');
$innewpassword2=qa_post_text('newpassword2');
$errors=array();
if (!qa_check_form_security_code('password', qa_post_text('code')))
$errors['page']=qa_lang_html('misc/form_security_again');
if ($haspassword && (strtolower(qa_db_calc_passcheck($inoldpassword, $useraccount['passsalt'])) != strtolower($useraccount['passcheck'])))
$errors['oldpassword']=qa_lang('users/password_wrong');
$useraccount['password']=$inoldpassword;
$errors=$errors+qa_password_validate($innewpassword1, $useraccount); // array union
if ($innewpassword1 != $innewpassword2)
$errors['newpassword2']=qa_lang('users/password_mismatch');
else {
$errors=array();
if (empty($errors)) {
qa_db_user_set_password($userid, $innewpassword1);
qa_db_user_set($userid, 'sessioncode', ''); // stop old 'Remember me' style logins from still working
qa_set_logged_in_user($userid, $useraccount['handle'], false, $useraccount['sessionsource']); // reinstate this specific session
qa_report_event('u_password', $userid, $useraccount['handle'], qa_cookie_get());
qa_redirect('account', array('state' => 'password-changed'));
if ($haspassword && (strtolower(qa_db_calc_passcheck($inoldpassword, $useraccount['passsalt'])) != strtolower($useraccount['passcheck'])))
$errors['oldpassword']=qa_lang('users/password_wrong');
$useraccount['password']=$inoldpassword;
$errors=$errors+qa_password_validate($innewpassword1, $useraccount); // array union
if ($innewpassword1 != $innewpassword2)
$errors['newpassword2']=qa_lang('users/password_mismatch');
if (empty($errors)) {
qa_db_user_set_password($userid, $innewpassword1);
qa_db_user_set($userid, 'sessioncode', ''); // stop old 'Remember me' style logins from still working
qa_set_logged_in_user($userid, $useraccount['handle'], false, $useraccount['sessionsource']); // reinstate this specific session
qa_report_event('u_password', $userid, $useraccount['handle'], qa_cookie_get());
qa_redirect('account', array('state' => 'password-changed'));
}
}
}
......@@ -185,7 +199,8 @@
$qa_content=qa_content_prepare();
$qa_content['title']=qa_lang_html('profile/my_account_title');
$qa_content['title']=qa_lang_html('profile/my_account_title');
$qa_content['error']=@$errors['page'];
$qa_content['form_profile']=array(
'tags' => 'ENCTYPE="multipart/form-data" METHOD="POST" ACTION="'.qa_self_html().'"',
......@@ -229,6 +244,14 @@
'note' => qa_lang_html('users/private_messages_explanation'),
),
'wall' => array(
'label' => qa_lang_html('users/wall_posts'),
'tags' => 'NAME="wall"',
'type' => 'checkbox',
'value' => !($useraccount['flags'] & QA_USER_FLAGS_NO_WALL_POSTS),
'note' => qa_lang_html('users/wall_posts_explanation'),
),
'mailings' => array(
'label' => qa_lang_html('users/mass_mailings'),
'tags' => 'NAME="mailings"',
......@@ -248,7 +271,8 @@
),
'hidden' => array(
'dosaveprofile' => '1'
'dosaveprofile' => '1',
'code' => qa_get_form_security_code('account'),
),
);
......@@ -258,6 +282,9 @@
if (!qa_opt('allow_private_messages'))
unset($qa_content['form_profile']['fields']['messages']);
if (!qa_opt('allow_user_walls'))
unset($qa_content['form_profile']['fields']['wall']);
if (!qa_opt('mailing_enabled'))
unset($qa_content['form_profile']['fields']['mailings']);
......@@ -381,6 +408,7 @@
'hidden' => array(
'dochangepassword' => '1',
'code' => qa_get_form_security_code('password'),
),
);
......
......@@ -32,7 +32,6 @@
require_once QA_INCLUDE_DIR.'qa-db-selects.php';
require_once QA_INCLUDE_DIR.'qa-app-format.php';
require_once QA_INCLUDE_DIR.'qa-app-updates.php';
require_once QA_INCLUDE_DIR.'qa-app-q-list.php';
$categoryslugs=qa_request_parts(1);
......@@ -42,14 +41,13 @@
// Get lists of recent activity in all its forms, plus category information
@list($questions1, $questions2, $questions3, $questions4, $categories, $categoryid, $favorite)=qa_db_select_with_pending(
list($questions1, $questions2, $questions3, $questions4, $categories, $categoryid)=qa_db_select_with_pending(
qa_db_qs_selectspec($userid, 'created', 0, $categoryslugs, null, false, false, qa_opt_if_loaded('page_size_activity')),
qa_db_recent_a_qs_selectspec($userid, 0, $categoryslugs),
qa_db_recent_c_qs_selectspec($userid, 0, $categoryslugs),
qa_db_recent_edit_qs_selectspec($userid, 0, $categoryslugs),
qa_db_category_nav_selectspec($categoryslugs, false, false, true),
$countslugs ? qa_db_slugs_to_category_id_selectspec($categoryslugs) : null,
($countslugs && isset($userid)) ? qa_db_is_favorite_selectspec($userid, QA_ENTITY_CATEGORY, $categoryslugs) : null
$countslugs ? qa_db_slugs_to_category_id_selectspec($categoryslugs) : null
);
if ($countslugs) {
......@@ -82,8 +80,7 @@
qa_opt('feed_for_activity') ? 'activity' : null, // prefix for RSS feed paths (null to hide)
qa_html_suggest_qs_tags(qa_using_tags(), qa_category_path_request($categories, $categoryid)), // suggest what to do next
null, // page link params
null, // category nav params
$favorite // has user favorited this category
null // category nav params
);
......
<?php
/*
Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/
File: qa-include/qa-page-admin-approve.php
Version: See define()s at top of qa-include/qa-base.php
Description: Controller for admin page showing new users waiting for approval
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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-admin.php';
require_once QA_INCLUDE_DIR.'qa-db-admin.php';
// Check we're not using single-sign on integration
if (QA_FINAL_EXTERNAL_USERS)
qa_fatal_error('User accounts are handled by external code');
// Find most flagged questions, answers, comments
$userid=qa_get_logged_in_userid();
$users=qa_db_get_unapproved_users(qa_opt('page_size_users'));
$userfields=qa_db_select_with_pending(qa_db_userfields_selectspec());
// Check admin privileges (do late to allow one DB query)
if (qa_get_logged_in_level()<QA_USER_LEVEL_MODERATOR) {
$qa_content=qa_content_prepare();
$qa_content['error']=qa_lang_html('users/no_permission');
return $qa_content;
}
// Check to see if any were approved or blocked here
$pageerror=qa_admin_check_clicks();
// Prepare content for theme
$qa_content=qa_content_prepare();
$qa_content['title']=qa_lang_html('admin/approve_users_title');
$qa_content['error']=isset($pageerror) ? $pageerror : qa_admin_page_error();
$qa_content['message_list']=array(
'form' => array(
'tags' => 'METHOD="POST" ACTION="'.qa_self_html().'"',
'hidden' => array(
'code' => qa_get_form_security_code('admin/click'),
),
),
'messages' => array(),
);
if (count($users)) {
foreach ($users as $user) {
$message=array();
$message['tags']='ID="p'.qa_html($user['userid']).'"'; // use p prefix for qa_admin_click() in qa-admin.js
$message['content']=qa_lang_html('users/registered_label').' '.
strtr(qa_lang_html('users/x_ago_from_y'), array(
'^1' => qa_time_to_string(qa_opt('db_time')-$user['created']),
'^2' => qa_ip_anchor_html($user['createip']),
)).'<br/>';
$htmlemail=qa_html($user['email']);
$message['content'].=qa_lang_html('users/email_label').' <A HREF="mailto:'.$htmlemail.'">'.$htmlemail.'</A>';
foreach ($userfields as $userfield)
if (strlen(@$user['profile'][$userfield['title']]))
$message['content'].='<br/>'.qa_html($userfield['content'].': '.$user['profile'][$userfield['title']]);
$message['meta_order']=qa_lang_html('main/meta_order');
$message['who']['data']=qa_get_one_user_html($user['handle']);
$message['form']=array(
'style' => 'light',
'buttons' => array(
'approve' => array(
'tags' => 'NAME="admin_'.$user['userid'].'_userapprove" onclick="return qa_admin_click(this);"',
'label' => qa_lang_html('question/approve_button'),
),
'block' => array(
'tags' => 'NAME="admin_'.$user['userid'].'_userblock" onclick="return qa_admin_click(this);"',
'label' => qa_lang_html('admin/block_button'),
),
),
);
$qa_content['message_list']['messages'][]=$message;
}
} else
$qa_content['title']=qa_lang_html('admin/no_unapproved_found');
$qa_content['navigation']['sub']=qa_admin_sub_navigation();
$qa_content['script_rel'][]='qa-content/qa-admin.js?'.QA_VERSION;
return $qa_content;
/*
Omit PHP closing tag to help avoid accidental output
*/
\ No newline at end of file
......@@ -80,14 +80,20 @@
$hassubcategory=true;
// Process saving options
$savedoptions=false;
$savedoptions=false;
$securityexpired=false;
if (qa_clicked('dosaveoptions')) {
qa_set_option('allow_no_category', (int)qa_post_text('option_allow_no_category'));
qa_set_option('allow_no_sub_category', (int)qa_post_text('option_allow_no_sub_category'));
$savedoptions=true;
if (!qa_check_form_security_code('admin/categories', qa_post_text('code')))
$securityexpired=true;
else {
qa_set_option('allow_no_category', (int)qa_post_text('option_allow_no_category'));
qa_set_option('allow_no_sub_category', (int)qa_post_text('option_allow_no_sub_category'));
$savedoptions=true;
}
}
......@@ -102,13 +108,20 @@
qa_redirect(qa_request(), array('edit' => @$editcategory['parentid']));
} elseif (qa_clicked('dosetmissing')) {
$inreassign=qa_get_category_field_value('reassign');
qa_db_category_reassign($editcategory['categoryid'], $inreassign);
qa_redirect(qa_request(), array('recalc' => 1, 'edit' => $editcategory['categoryid']));
if (!qa_check_form_security_code('admin/categories', qa_post_text('code')))
$securityexpired=true;
else {
$inreassign=qa_get_category_field_value('reassign');
qa_db_category_reassign($editcategory['categoryid'], $inreassign);
qa_redirect(qa_request(), array('recalc' => 1, 'edit' => $editcategory['categoryid']));
}
} elseif (qa_clicked('dosavecategory')) {
if (qa_post_text('dodelete')) {
if (!qa_check_form_security_code('admin/categories', qa_post_text('code')))
$securityexpired=true;
elseif (qa_post_text('dodelete')) {
if (!$hassubcategory) {
$inreassign=qa_get_category_field_value('reassign');
......@@ -230,8 +243,7 @@
$qa_content=qa_content_prepare();
$qa_content['title']=qa_lang_html('admin/admin_title').' - '.qa_lang_html('admin/categories_title');
$qa_content['error']=qa_admin_page_error();
$qa_content['error']=$securityexpired ? qa_lang_html('admin/form_security_expired') : qa_admin_page_error();
if ($setmissing) {
$qa_content['form']=array(
......@@ -263,6 +275,7 @@
'dosetmissing' => '1', // for IE
'edit' => @$editcategory['categoryid'],
'missing' => '1',
'code' => qa_get_form_security_code('admin/categories'),
),
);
......@@ -328,6 +341,7 @@
'edit' => @$editcategory['categoryid'],
'parent' => @$editcategory['parentid'],
'setparent' => (int)$setparent,
'code' => qa_get_form_security_code('admin/categories'),
),
);
......@@ -534,6 +548,10 @@
'label' => qa_lang_html('admin/add_category_button'),
),
),
'hidden' => array(
'code' => qa_get_form_security_code('admin/categories'),
),
);
if (count($categories)) {
......
......@@ -45,7 +45,7 @@
// Check admin privileges (do late to allow one DB query)
if (qa_user_permit_error('permit_hide_show')) {
if (qa_user_maximum_permit_error('permit_hide_show')) {
$qa_content=qa_content_prepare();
$qa_content['error']=qa_lang_html('users/no_permission');
return $qa_content;
......@@ -54,7 +54,15 @@
// Check to see if any were cleared or hidden here
qa_admin_check_clicks();
$pageerror=qa_admin_check_clicks();
// Remove questions the user has no permission to hide/show
if (qa_user_permit_error('permit_hide_show')) // if user not allowed to show/hide all posts
foreach ($questions as $index => $question)
if (qa_user_post_permit_error('permit_hide_show', $question))
unset($questions[$index]);
// Get information for users
......@@ -67,12 +75,15 @@
$qa_content=qa_content_prepare();
$qa_content['title']=qa_lang_html('admin/most_flagged_title');
$qa_content['error']=qa_admin_page_error();
$qa_content['error']=isset($pageerror) ? $pageerror : qa_admin_page_error();
$qa_content['q_list']=array(
'form' => array(
'tags' => 'METHOD="POST" ACTION="'.qa_self_html().'"',
'hidden' => array(
'code' => qa_get_form_security_code('admin/click'),
),
),
'qs' => array(),
......@@ -84,7 +95,7 @@
$postid=qa_html(isset($question['opostid']) ? $question['opostid'] : $question['postid']);
$elementid='p'.$postid;
$htmloptions=qa_post_html_defaults('Q');
$htmloptions=qa_post_html_options($question);
$htmloptions['voteview']=false;
$htmloptions['tagsview']=($question['obasetype']=='Q');
$htmloptions['answersview']=false;
......
......@@ -48,10 +48,7 @@
// Check admin privileges (do late to allow one DB query)
$allowhideshow=!qa_user_permit_error('permit_hide_show');
$allowdeletehidden=!qa_user_permit_error('permit_delete_hidden');
if (!($allowhideshow || $allowdeletehidden)) {
if (qa_user_maximum_permit_error('permit_hide_show') && qa_user_maximum_permit_error('permit_delete_hidden')) {
$qa_content=qa_content_prepare();
$qa_content['error']=qa_lang_html('users/no_permission');
return $qa_content;
......@@ -60,13 +57,21 @@
// Check to see if any have been reshown or deleted
qa_admin_check_clicks();
$pageerror=qa_admin_check_clicks();
// Combine sets of questions, get information for users
// Combine sets of questions and remove those this user has no permissions for
$questions=qa_any_sort_by_date(array_merge($hiddenquestions, $hiddenanswers, $hiddencomments));
if (qa_user_permit_error('permit_hide_show') && qa_user_permit_error('permit_delete_hidden')) // not allowed to see all hidden posts
foreach ($questions as $index => $question)
if (qa_user_post_permit_error('permit_hide_show', $question) && qa_user_post_permit_error('permit_delete_hidden', $question))
unset($questions[$index]);
// Get information for users
$usershtml=qa_userids_handles_html(qa_any_get_userids_handles($questions));
......@@ -84,12 +89,15 @@
$qa_content=qa_content_prepare();
$qa_content['title']=qa_lang_html('admin/recent_hidden_title');
$qa_content['error']=qa_admin_page_error();
$qa_content['error']=isset($pageerror) ? $pageerror : qa_admin_page_error();
$qa_content['q_list']=array(
'form' => array(
'tags' => 'METHOD="POST" ACTION="'.qa_self_html().'"',
'hidden' => array(
'code' => qa_get_form_security_code('admin/click'),
),
),
'qs' => array(),
......@@ -99,7 +107,7 @@
foreach ($questions as $key => $question) {
$elementid='p'.$qhiddenpostid[$key];
$htmloptions=qa_post_html_defaults('Q');
$htmloptions=qa_post_html_options($question);
$htmloptions['voteview']=false;
$htmloptions['tagsview']=!isset($question['opostid']);
$htmloptions['answersview']=false;
......@@ -120,13 +128,13 @@
$buttons=array();
if ($allowhideshow)
if (!qa_user_post_permit_error('permit_hide_show', $question))
$buttons['reshow']=array(
'tags' => 'NAME="admin_'.qa_html($qhiddenpostid[$key]).'_reshow" onclick="return qa_admin_click(this);"',
'label' => qa_lang_html('question/reshow_button'),
);
if ($allowdeletehidden && !$dependcounts[$qhiddenpostid[$key]])
if ((!qa_user_post_permit_error('permit_delete_hidden', $question)) && !$dependcounts[$qhiddenpostid[$key]])
$buttons['delete']=array(
'tags' => 'NAME="admin_'.qa_html($qhiddenpostid[$key]).'_delete" onclick="return qa_admin_click(this);"',
'label' => qa_lang_html('question/delete_button'),
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment