Commit ec46ded0 by Scott Vivian

Trim trailing space

parent 0961d5dd
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<head> <head>
<meta http-equiv="refresh" content="2;url=http://www.question2answer.org/versions.php"> <meta http-equiv="refresh" content="2;url=http://www.question2answer.org/versions.php">
</head> </head>
<body> <body>
Redirecting... if nothing happens, <a href="http://www.question2answer.org/versions.php">click here</a>. Redirecting... if nothing happens, <a href="http://www.question2answer.org/versions.php">click here</a>.
</body> </body>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<head> <head>
<meta http-equiv="refresh" content="2;url=http://www.question2answer.org/license.php"> <meta http-equiv="refresh" content="2;url=http://www.question2answer.org/license.php">
</head> </head>
<body> <body>
Redirecting... if nothing happens, <a href="http://www.question2answer.org/license.php">click here</a>. Redirecting... if nothing happens, <a href="http://www.question2answer.org/license.php">click here</a>.
</body> </body>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<head> <head>
<meta http-equiv="refresh" content="2;url=http://www.question2answer.org/install.php"> <meta http-equiv="refresh" content="2;url=http://www.question2answer.org/install.php">
</head> </head>
<body> <body>
Redirecting... if nothing happens, <a href="http://www.question2answer.org/install.php">click here</a>. Redirecting... if nothing happens, <a href="http://www.question2answer.org/install.php">click here</a>.
</body> </body>
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-config-example.php File: qa-config-example.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: After renaming, use this to set up database details and other stuff Description: After renaming, use this to set up database details and other stuff
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -34,10 +34,10 @@ ...@@ -34,10 +34,10 @@
define('QA_MYSQL_USERNAME', 'your-mysql-username'); define('QA_MYSQL_USERNAME', 'your-mysql-username');
define('QA_MYSQL_PASSWORD', 'your-mysql-password'); define('QA_MYSQL_PASSWORD', 'your-mysql-password');
define('QA_MYSQL_DATABASE', 'your-mysql-db-name'); define('QA_MYSQL_DATABASE', 'your-mysql-db-name');
/* /*
Ultra-concise installation instructions: Ultra-concise installation instructions:
1. Create a MySQL database. 1. Create a MySQL database.
2. Create a MySQL user with full permissions for that database. 2. Create a MySQL user with full permissions for that database.
3. Rename this file to qa-config.php. 3. Rename this file to qa-config.php.
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
*/ */
define('QA_MYSQL_TABLE_PREFIX', 'qa_'); define('QA_MYSQL_TABLE_PREFIX', 'qa_');
/* /*
If you wish, you can define QA_MYSQL_USERS_PREFIX separately from QA_MYSQL_TABLE_PREFIX. If you wish, you can define QA_MYSQL_USERS_PREFIX separately from QA_MYSQL_TABLE_PREFIX.
If so, it is used instead of QA_MYSQL_TABLE_PREFIX as the prefix for tables containing If so, it is used instead of QA_MYSQL_TABLE_PREFIX as the prefix for tables containing
...@@ -76,16 +76,16 @@ ...@@ -76,16 +76,16 @@
also have the same value for QA_BLOBS_DIRECTORY. also have the same value for QA_BLOBS_DIRECTORY.
If there are already some BLOBs stored in the database from previous uploads, click the 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. '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/'); 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 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 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. useful if you're running multiple Q2A sites on subdomains with a shared user base.
define('QA_COOKIE_DOMAIN', '.example.com'); // be sure to keep the leading period define('QA_COOKIE_DOMAIN', '.example.com'); // be sure to keep the leading period
*/ */
...@@ -94,7 +94,7 @@ ...@@ -94,7 +94,7 @@
The key of each array element should be the standard part of the path, e.g. 'questions', The key of each array element should be the standard part of the path, e.g. 'questions',
and the value should be the replacement for that standard part, e.g. 'topics'. If you edit this and the value should be the replacement for that standard part, e.g. 'topics'. If you edit this
file in UTF-8 encoding you can also use non-ASCII characters in these URLs. file in UTF-8 encoding you can also use non-ASCII characters in these URLs.
$QA_CONST_PATH_MAP=array( $QA_CONST_PATH_MAP=array(
'questions' => 'topics', 'questions' => 'topics',
'categories' => 'sections', 'categories' => 'sections',
...@@ -107,11 +107,11 @@ ...@@ -107,11 +107,11 @@
Set QA_EXTERNAL_USERS to true to use your user identification code in qa-external/qa-external-users.php Set QA_EXTERNAL_USERS to true to use your user identification code in qa-external/qa-external-users.php
This allows you to integrate with your existing user database and management system. For more details, This allows you to integrate with your existing user database and management system. For more details,
consult the online documentation on installing Question2Answer with single sign-on. consult the online documentation on installing Question2Answer with single sign-on.
The constants QA_EXTERNAL_LANG and QA_EXTERNAL_EMAILER are deprecated from Q2A 1.5 since the same The constants QA_EXTERNAL_LANG and QA_EXTERNAL_EMAILER are deprecated from Q2A 1.5 since the same
effect can now be achieved in plugins by using function overrides. effect can now be achieved in plugins by using function overrides.
*/ */
define('QA_EXTERNAL_USERS', false); define('QA_EXTERNAL_USERS', false);
/* /*
...@@ -119,26 +119,26 @@ ...@@ -119,26 +119,26 @@
database, define QA_WORDPRESS_INTEGRATE_PATH as the full path to the WordPress directory database, define QA_WORDPRESS_INTEGRATE_PATH as the full path to the WordPress directory
containing wp-load.php. You do not need to set the QA_MYSQL_* constants above since these containing wp-load.php. You do not need to set the QA_MYSQL_* constants above since these
will be taken from WordPress automatically. See online documentation for more details. will be taken from WordPress automatically. See online documentation for more details.
define('QA_WORDPRESS_INTEGRATE_PATH', '/PATH/TO/WORDPRESS'); define('QA_WORDPRESS_INTEGRATE_PATH', '/PATH/TO/WORDPRESS');
*/ */
/* /*
Some settings to help optimize your Question2Answer site's performance. Some settings to help optimize your Question2Answer site's performance.
If QA_HTML_COMPRESSION is true, HTML web pages will be output using Gzip compression, if If QA_HTML_COMPRESSION is true, HTML web pages will be output using Gzip compression, if
the user's browser indicates this is supported. This will increase the performance of your the user's browser indicates this is supported. This will increase the performance of your
site, but may make debugging harder if PHP does not complete execution. site, but may make debugging harder if PHP does not complete execution.
QA_MAX_LIMIT_START is the maximum start parameter that can be requested, for paging through QA_MAX_LIMIT_START is the maximum start parameter that can be requested, for paging through
long lists of questions, etc... As the start parameter gets higher, queries tend to get long lists of questions, etc... As the start parameter gets higher, queries tend to get
slower, since MySQL must examine more information. Very high start numbers are usually only slower, since MySQL must examine more information. Very high start numbers are usually only
requested by search engine robots anyway. requested by search engine robots anyway.
If a word is used QA_IGNORED_WORDS_FREQ times or more in a particular way, it is ignored If a word is used QA_IGNORED_WORDS_FREQ times or more in a particular way, it is ignored
when searching or finding related questions. This saves time by ignoring words which are so when searching or finding related questions. This saves time by ignoring words which are so
common that they are probably not worth matching on. common that they are probably not worth matching on.
Set QA_ALLOW_UNINDEXED_QUERIES to true if you don't mind running some database queries which Set QA_ALLOW_UNINDEXED_QUERIES to true if you don't mind running some database queries which
are not indexed efficiently. For example, this will enable browsing unanswered questions per are not indexed efficiently. For example, this will enable browsing unanswered questions per
category. If your database becomes large, these queries could become costly. category. If your database becomes large, these queries could become costly.
...@@ -146,15 +146,15 @@ ...@@ -146,15 +146,15 @@
Set QA_OPTIMIZE_LOCAL_DB to true if your web server and MySQL are running on the same box. Set QA_OPTIMIZE_LOCAL_DB to true if your web server and MySQL are running on the same box.
When viewing a page on your site, this will use many simple MySQL queries instead of fewer When viewing a page on your site, this will use many simple MySQL queries instead of fewer
complex ones, which makes sense since there is no latency for localhost access. complex ones, which makes sense since there is no latency for localhost access.
Set QA_OPTIMIZE_DISTANT_DB to true if your web server and MySQL are far enough apart to Set QA_OPTIMIZE_DISTANT_DB to true if your web server and MySQL are far enough apart to
create significant latency. This will minimize the number of database queries as much as create significant latency. This will minimize the number of database queries as much as
is possible, even at the cost of significant additional processing at each end. is possible, even at the cost of significant additional processing at each end.
Set QA_PERSISTENT_CONN_DB to true to use persistent database connections. Only use this if Set QA_PERSISTENT_CONN_DB to true to use persistent database connections. Only use this if
you are absolutely sure it is a good idea under your setup - generally it is not. you are absolutely sure it is a good idea under your setup - generally it is not.
For more information: http://www.php.net/manual/en/features.persistent-connections.php For more information: http://www.php.net/manual/en/features.persistent-connections.php
Set QA_DEBUG_PERFORMANCE to true to show detailed performance profiling information at the Set QA_DEBUG_PERFORMANCE to true to show detailed performance profiling information at the
bottom of every Question2Answer page. bottom of every Question2Answer page.
*/ */
...@@ -167,12 +167,12 @@ ...@@ -167,12 +167,12 @@
define('QA_OPTIMIZE_DISTANT_DB', false); define('QA_OPTIMIZE_DISTANT_DB', false);
define('QA_PERSISTENT_CONN_DB', false); define('QA_PERSISTENT_CONN_DB', false);
define('QA_DEBUG_PERFORMANCE', false); define('QA_DEBUG_PERFORMANCE', false);
/* /*
And lastly... if you want to, you can predefine any constant from qa-db-maxima.php in this And lastly... if you want to, you can predefine any constant from qa-db-maxima.php in this
file to override the default setting. Just make sure you know what you're doing! file to override the default setting. Just make sure you know what you're doing!
*/ */
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-answer.php File: qa-include/qa-ajax-answer.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax create answer requests Description: Server-side response to Ajax create answer requests
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -30,10 +30,10 @@ ...@@ -30,10 +30,10 @@
// Load relevant information about this question // Load relevant information about this question
$questionid=qa_post_text('a_questionid'); $questionid=qa_post_text('a_questionid');
$userid=qa_get_logged_in_userid(); $userid=qa_get_logged_in_userid();
list($question, $childposts)=qa_db_select_with_pending( list($question, $childposts)=qa_db_select_with_pending(
qa_db_full_post_selectspec($userid, $questionid), qa_db_full_post_selectspec($userid, $questionid),
qa_db_full_child_posts_selectspec($userid, $questionid) qa_db_full_child_posts_selectspec($userid, $questionid)
...@@ -52,35 +52,35 @@ ...@@ -52,35 +52,35 @@
// Try to create the new answer // Try to create the new answer
$usecaptcha=qa_user_use_captcha(qa_user_level_for_post($question)); $usecaptcha=qa_user_use_captcha(qa_user_level_for_post($question));
$answers=qa_page_q_load_as($question, $childposts); $answers=qa_page_q_load_as($question, $childposts);
$answerid=qa_page_q_add_a_submit($question, $answers, $usecaptcha, $in, $errors); $answerid=qa_page_q_add_a_submit($question, $answers, $usecaptcha, $in, $errors);
// If successful, page content will be updated via Ajax // If successful, page content will be updated via Ajax
if (isset($answerid)) { if (isset($answerid)) {
$answer=qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $answerid)); $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 $question=$question+qa_page_q_post_rules($question, null, null, $childposts); // array union
$answer=$answer+qa_page_q_post_rules($answer, $question, $answers, null); $answer=$answer+qa_page_q_post_rules($answer, $question, $answers, null);
$usershtml=qa_userids_handles_html(array($answer), true); $usershtml=qa_userids_handles_html(array($answer), true);
$a_view=qa_page_q_answer_view($question, $answer, false, $usershtml, false); $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); $themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-answer', null, null);
echo "QA_AJAX_RESPONSE\n1\n"; echo "QA_AJAX_RESPONSE\n1\n";
// Send back whether the 'answer' button should still be visible // Send back whether the 'answer' button should still be visible
echo (int)qa_opt('allow_multi_answers')."\n"; echo (int)qa_opt('allow_multi_answers')."\n";
// Send back the count of answers // Send back the count of answers
$countanswers=$question['acount']+1; $countanswers=$question['acount']+1;
if ($countanswers==1) if ($countanswers==1)
...@@ -96,11 +96,11 @@ ...@@ -96,11 +96,11 @@
return; return;
} }
} }
echo "QA_AJAX_RESPONSE\n0\n"; // fall back to non-Ajax submission if there were any problems echo "QA_AJAX_RESPONSE\n0\n"; // fall back to non-Ajax submission if there were any problems
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
*/ */
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-asktitle.php File: qa-include/qa-ajax-asktitle.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax request based on ask a question title Description: Server-side response to Ajax request based on ask a question title
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
require_once QA_INCLUDE_DIR.'qa-db-selects.php'; require_once QA_INCLUDE_DIR.'qa-db-selects.php';
require_once QA_INCLUDE_DIR.'qa-util-string.php'; require_once QA_INCLUDE_DIR.'qa-util-string.php';
// Collect the information we need from the database // Collect the information we need from the database
...@@ -36,29 +36,29 @@ ...@@ -36,29 +36,29 @@
if ($doaskcheck || $doexampletags) { if ($doaskcheck || $doexampletags) {
$countqs=max($doexampletags ? QA_DB_RETRIEVE_ASK_TAG_QS : 0, $doaskcheck ? qa_opt('page_size_ask_check_qs') : 0); $countqs=max($doexampletags ? QA_DB_RETRIEVE_ASK_TAG_QS : 0, $doaskcheck ? qa_opt('page_size_ask_check_qs') : 0);
$relatedquestions=qa_db_select_with_pending( $relatedquestions=qa_db_select_with_pending(
qa_db_search_posts_selectspec(null, qa_string_to_words($intitle), null, null, null, null, 0, false, $countqs) qa_db_search_posts_selectspec(null, qa_string_to_words($intitle), null, null, null, null, 0, false, $countqs)
); );
} }
// Collect example tags if appropriate // Collect example tags if appropriate
if ($doexampletags) { if ($doexampletags) {
require_once QA_INCLUDE_DIR.'qa-app-format.php'; require_once QA_INCLUDE_DIR.'qa-app-format.php';
$tagweight=array(); $tagweight=array();
foreach ($relatedquestions as $question) { foreach ($relatedquestions as $question) {
$tags=qa_tagstring_to_tags($question['tags']); $tags=qa_tagstring_to_tags($question['tags']);
foreach ($tags as $tag) foreach ($tags as $tag)
@$tagweight[$tag]+=exp($question['score']); @$tagweight[$tag]+=exp($question['score']);
} }
arsort($tagweight, SORT_NUMERIC); arsort($tagweight, SORT_NUMERIC);
$exampletags=array(); $exampletags=array();
$minweight=exp(qa_match_to_min_score(qa_opt('match_example_tags'))); $minweight=exp(qa_match_to_min_score(qa_opt('match_example_tags')));
$maxcount=qa_opt('page_size_ask_tags'); $maxcount=qa_opt('page_size_ask_tags');
...@@ -78,36 +78,36 @@ ...@@ -78,36 +78,36 @@
// Output the response header and example tags // Output the response header and example tags
echo "QA_AJAX_RESPONSE\n1\n"; echo "QA_AJAX_RESPONSE\n1\n";
echo strtr(qa_html(implode(',', $exampletags)), "\r\n", ' ')."\n"; echo strtr(qa_html(implode(',', $exampletags)), "\r\n", ' ')."\n";
// Collect and output the list of related questions // Collect and output the list of related questions
if ($doaskcheck) { if ($doaskcheck) {
require_once QA_INCLUDE_DIR.'qa-app-format.php'; require_once QA_INCLUDE_DIR.'qa-app-format.php';
$count=0; $count=0;
$minscore=qa_match_to_min_score(qa_opt('match_ask_check_qs')); $minscore=qa_match_to_min_score(qa_opt('match_ask_check_qs'));
$maxcount=qa_opt('page_size_ask_check_qs'); $maxcount=qa_opt('page_size_ask_check_qs');
foreach ($relatedquestions as $question) { foreach ($relatedquestions as $question) {
if ($question['score']<$minscore) if ($question['score']<$minscore)
break; break;
if (!$count) if (!$count)
echo qa_lang_html('question/ask_same_q').'<br/>'; echo qa_lang_html('question/ask_same_q').'<br/>';
echo strtr( echo strtr(
'<a href="'.qa_q_path_html($question['postid'], $question['title']).'" target="_blank">'.qa_html($question['title']).'</a><br/>', '<a href="'.qa_q_path_html($question['postid'], $question['title']).'" target="_blank">'.qa_html($question['title']).'</a><br/>',
"\r\n", ' ' "\r\n", ' '
)."\n"; )."\n";
if ((++$count)>=$maxcount) if ((++$count)>=$maxcount)
break; break;
} }
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-category.php File: qa-include/qa-ajax-category.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax category information requests Description: Server-side response to Ajax category information requests
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -25,24 +25,24 @@ ...@@ -25,24 +25,24 @@
*/ */
require_once QA_INCLUDE_DIR.'qa-db-selects.php'; require_once QA_INCLUDE_DIR.'qa-db-selects.php';
$categoryid=qa_post_text('categoryid'); $categoryid=qa_post_text('categoryid');
if (!strlen($categoryid)) if (!strlen($categoryid))
$categoryid=null; $categoryid=null;
list($fullcategory, $categories)=qa_db_select_with_pending( list($fullcategory, $categories)=qa_db_select_with_pending(
qa_db_full_category_selectspec($categoryid, true), qa_db_full_category_selectspec($categoryid, true),
qa_db_category_sub_selectspec($categoryid) qa_db_category_sub_selectspec($categoryid)
); );
echo "QA_AJAX_RESPONSE\n1\n"; echo "QA_AJAX_RESPONSE\n1\n";
echo qa_html(strtr(@$fullcategory['content'], "\r\n", ' ')); // category description echo qa_html(strtr(@$fullcategory['content'], "\r\n", ' ')); // category description
foreach ($categories as $category) foreach ($categories as $category)
echo "\n".$category['categoryid'].'/'.$category['title']; // subcategory information echo "\n".$category['categoryid'].'/'.$category['title']; // subcategory information
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-click-admin.php File: qa-include/qa-ajax-click-admin.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax single clicks on posts in admin section Description: Server-side response to Ajax single clicks on posts in admin section
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -38,8 +38,8 @@ ...@@ -38,8 +38,8 @@
echo "QA_AJAX_RESPONSE\n1\n"; echo "QA_AJAX_RESPONSE\n1\n";
else else
echo "QA_AJAX_RESPONSE\n0\n".qa_lang('main/general_error'); echo "QA_AJAX_RESPONSE\n0\n".qa_lang('main/general_error');
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
*/ */
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-click-answer.php File: qa-include/qa-ajax-click-answer.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax single clicks on answer Description: Server-side response to Ajax single clicks on answer
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
qa_db_full_child_posts_selectspec($userid, $questionid), qa_db_full_child_posts_selectspec($userid, $questionid),
qa_db_full_child_posts_selectspec($userid, $answerid) qa_db_full_child_posts_selectspec($userid, $answerid)
); );
// Check if there was an operation that succeeded // Check if there was an operation that succeeded
...@@ -57,63 +57,63 @@ ...@@ -57,63 +57,63 @@
$question=$question+qa_page_q_post_rules($question, null, null, $qchildposts); // array union $question=$question+qa_page_q_post_rules($question, null, null, $qchildposts); // array union
$answer=$answer+qa_page_q_post_rules($answer, $question, $qchildposts, $achildposts); $answer=$answer+qa_page_q_post_rules($answer, $question, $qchildposts, $achildposts);
if (qa_page_q_single_click_a($answer, $question, $answers, $achildposts, false, $error)) { if (qa_page_q_single_click_a($answer, $question, $answers, $achildposts, false, $error)) {
list($answer, $question)=qa_db_select_with_pending( list($answer, $question)=qa_db_select_with_pending(
qa_db_full_post_selectspec($userid, $answerid), qa_db_full_post_selectspec($userid, $answerid),
qa_db_full_post_selectspec($userid, $questionid) qa_db_full_post_selectspec($userid, $questionid)
); );
// If so, page content to be updated via Ajax // If so, page content to be updated via Ajax
echo "QA_AJAX_RESPONSE\n1\n"; echo "QA_AJAX_RESPONSE\n1\n";
// Send back new count of answers // Send back new count of answers
$countanswers=$question['acount']; $countanswers=$question['acount'];
if ($countanswers==1) if ($countanswers==1)
echo qa_lang_html('question/1_answer_title'); echo qa_lang_html('question/1_answer_title');
else else
echo qa_lang_html_sub('question/x_answers_title', $countanswers); echo qa_lang_html_sub('question/x_answers_title', $countanswers);
// If the answer was not deleted.... // If the answer was not deleted....
if (isset($answer)) { if (isset($answer)) {
$question=$question+qa_page_q_post_rules($question, null, null, $qchildposts); // array union $question=$question+qa_page_q_post_rules($question, null, null, $qchildposts); // array union
$answer=$answer+qa_page_q_post_rules($answer, $question, $qchildposts, $achildposts); $answer=$answer+qa_page_q_post_rules($answer, $question, $qchildposts, $achildposts);
foreach ($achildposts as $key => $achildpost) foreach ($achildposts as $key => $achildpost)
$achildposts[$key]=$achildpost+qa_page_q_post_rules($achildpost, $answer, $achildposts, null); $achildposts[$key]=$achildpost+qa_page_q_post_rules($achildpost, $answer, $achildposts, null);
$usershtml=qa_userids_handles_html(array_merge(array($answer), $achildposts), true); $usershtml=qa_userids_handles_html(array_merge(array($answer), $achildposts), true);
$a_view=qa_page_q_answer_view($question, $answer, ($answer['postid']==$question['selchildid']) && ($answer['type']=='A'), $a_view=qa_page_q_answer_view($question, $answer, ($answer['postid']==$question['selchildid']) && ($answer['type']=='A'),
$usershtml, false); $usershtml, false);
$a_view['c_list']=qa_page_q_comment_follow_list($question, $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); $themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-answer', null, null);
// ... send back the HTML for it // ... send back the HTML for it
echo "\n"; echo "\n";
$themeclass->a_list_item($a_view); $themeclass->a_list_item($a_view);
} }
return; return;
} }
} }
echo "QA_AJAX_RESPONSE\n0\n"; // fall back to non-Ajax submission if something failed echo "QA_AJAX_RESPONSE\n0\n"; // fall back to non-Ajax submission if something failed
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
*/ */
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-click-comment.php File: qa-include/qa-ajax-click-comment.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax single clicks on comments Description: Server-side response to Ajax single clicks on comments
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
qa_db_full_child_posts_selectspec($userid, $parentid) qa_db_full_child_posts_selectspec($userid, $parentid)
); );
// Check if there was an operation that succeeded // Check if there was an operation that succeeded
if ( if (
...@@ -56,45 +56,45 @@ ...@@ -56,45 +56,45 @@
((@$parent['basetype']=='Q') || (@$parent['basetype']=='A')) ((@$parent['basetype']=='Q') || (@$parent['basetype']=='A'))
) { ) {
$comment=$comment+qa_page_q_post_rules($comment, $parent, $children, null); // array union $comment=$comment+qa_page_q_post_rules($comment, $parent, $children, null); // array union
if (qa_page_q_single_click_c($comment, $question, $parent, $error)) { if (qa_page_q_single_click_c($comment, $question, $parent, $error)) {
$comment=qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $commentid)); $comment=qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $commentid));
// If so, page content to be updated via Ajax // If so, page content to be updated via Ajax
echo "QA_AJAX_RESPONSE\n1"; echo "QA_AJAX_RESPONSE\n1";
// If the comment was not deleted... // If the comment was not deleted...
if (isset($comment)) { if (isset($comment)) {
$parent=$parent+qa_page_q_post_rules($parent, ($questionid==$parentid) ? null : $question, null, $children); $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 // in theory we should retrieve the parent's siblings for the above, but they're not going to be relevant
$comment=$comment+qa_page_q_post_rules($comment, $parent, $children, null); $comment=$comment+qa_page_q_post_rules($comment, $parent, $children, null);
$usershtml=qa_userids_handles_html(array($comment), true); $usershtml=qa_userids_handles_html(array($comment), true);
$c_view=qa_page_q_comment_view($question, $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); $themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-comment', null, null);
// ... send back the HTML for it // ... send back the HTML for it
echo "\n"; echo "\n";
$themeclass->c_list_item($c_view); $themeclass->c_list_item($c_view);
} }
return; return;
} }
} }
echo "QA_AJAX_RESPONSE\n0\n"; // fall back to non-Ajax submission if something failed echo "QA_AJAX_RESPONSE\n0\n"; // fall back to non-Ajax submission if something failed
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
*/ */
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-click-wall.php File: qa-include/qa-ajax-click-wall.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax single clicks on wall posts Description: Server-side response to Ajax single clicks on wall posts
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -23,19 +23,19 @@ ...@@ -23,19 +23,19 @@
More about this license: http://www.question2answer.org/license.php 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-messages.php';
require_once QA_INCLUDE_DIR.'qa-app-users.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-app-cookies.php';
require_once QA_INCLUDE_DIR.'qa-db-selects.php'; require_once QA_INCLUDE_DIR.'qa-db-selects.php';
$tohandle=qa_post_text('handle'); $tohandle=qa_post_text('handle');
$start=(int)qa_post_text('start'); $start=(int)qa_post_text('start');
$usermessages=qa_db_select_with_pending(qa_db_recent_messages_selectspec(null, null, $tohandle, false, null, $start)); $usermessages=qa_db_select_with_pending(qa_db_recent_messages_selectspec(null, null, $tohandle, false, null, $start));
$usermessages=qa_wall_posts_add_rules($usermessages, $start); $usermessages=qa_wall_posts_add_rules($usermessages, $start);
foreach ($usermessages as $message) foreach ($usermessages as $message)
if (qa_clicked('m'.$message['messageid'].'_dodelete') && $message['deleteable']) if (qa_clicked('m'.$message['messageid'].'_dodelete') && $message['deleteable'])
if (qa_check_form_security_code('wall-'.$tohandle, qa_post_text('code'))) { if (qa_check_form_security_code('wall-'.$tohandle, qa_post_text('code'))) {
...@@ -43,8 +43,8 @@ ...@@ -43,8 +43,8 @@
echo "QA_AJAX_RESPONSE\n1\n"; echo "QA_AJAX_RESPONSE\n1\n";
return; return;
} }
echo "QA_AJAX_RESPONSE\n0\n"; echo "QA_AJAX_RESPONSE\n0\n";
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-comment.php File: qa-include/qa-ajax-comment.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax create comment requests Description: Server-side response to Ajax create comment requests
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
$questionid=qa_post_text('c_questionid'); $questionid=qa_post_text('c_questionid');
$parentid=qa_post_text('c_parentid'); $parentid=qa_post_text('c_parentid');
$userid=qa_get_logged_in_userid(); $userid=qa_get_logged_in_userid();
list($question, $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, $questionid),
qa_db_full_post_selectspec($userid, $parentid), qa_db_full_post_selectspec($userid, $parentid),
...@@ -59,37 +59,37 @@ ...@@ -59,37 +59,37 @@
// Try to create the new comment // Try to create the new comment
$usecaptcha=qa_user_use_captcha(qa_user_level_for_post($question)); $usecaptcha=qa_user_use_captcha(qa_user_level_for_post($question));
$commentid=qa_page_q_add_c_submit($question, $parent, $children, $usecaptcha, $in, $errors); $commentid=qa_page_q_add_c_submit($question, $parent, $children, $usecaptcha, $in, $errors);
// If successful, page content will be updated via Ajax // If successful, page content will be updated via Ajax
if (isset($commentid)) { if (isset($commentid)) {
$children=qa_db_select_with_pending(qa_db_full_child_posts_selectspec($userid, $parentid)); $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); $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 // 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) foreach ($children as $key => $child)
$children[$key]=$child+qa_page_q_post_rules($child, $parent, $children, null); $children[$key]=$child+qa_page_q_post_rules($child, $parent, $children, null);
$usershtml=qa_userids_handles_html($children, true); $usershtml=qa_userids_handles_html($children, true);
qa_sort_by($children, 'created'); qa_sort_by($children, 'created');
$c_list=qa_page_q_comment_follow_list($question, $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); $themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-comments', null, null);
echo "QA_AJAX_RESPONSE\n1\n"; echo "QA_AJAX_RESPONSE\n1\n";
// Send back the ID of the new comment // 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
...@@ -98,10 +98,10 @@ ...@@ -98,10 +98,10 @@
return; return;
} }
} }
echo "QA_AJAX_RESPONSE\n0\n"; // fall back to non-Ajax submission if there were any problems echo "QA_AJAX_RESPONSE\n0\n"; // fall back to non-Ajax submission if there were any problems
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
*/ */
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-favorite.php File: qa-include/qa-ajax-favorite.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax favorite requests Description: Server-side response to Ajax favorite requests
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -28,31 +28,31 @@ ...@@ -28,31 +28,31 @@
require_once QA_INCLUDE_DIR.'qa-app-cookies.php'; require_once QA_INCLUDE_DIR.'qa-app-cookies.php';
require_once QA_INCLUDE_DIR.'qa-app-favorites.php'; require_once QA_INCLUDE_DIR.'qa-app-favorites.php';
require_once QA_INCLUDE_DIR.'qa-app-format.php'; require_once QA_INCLUDE_DIR.'qa-app-format.php';
$entitytype=qa_post_text('entitytype'); $entitytype=qa_post_text('entitytype');
$entityid=qa_post_text('entityid'); $entityid=qa_post_text('entityid');
$setfavorite=qa_post_text('favorite'); $setfavorite=qa_post_text('favorite');
$userid=qa_get_logged_in_userid(); $userid=qa_get_logged_in_userid();
if (!qa_check_form_security_code('favorite-'.$entitytype.'-'.$entityid, qa_post_text('code'))) 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'); echo "QA_AJAX_RESPONSE\n0\n".qa_lang('misc/form_security_reload');
elseif (isset($userid)) { elseif (isset($userid)) {
$cookieid=qa_cookie_get(); $cookieid=qa_cookie_get();
qa_user_favorite_set($userid, qa_get_logged_in_handle(), $cookieid, $entitytype, $entityid, $setfavorite); qa_user_favorite_set($userid, qa_get_logged_in_handle(), $cookieid, $entitytype, $entityid, $setfavorite);
$favoriteform=qa_favorite_form($entitytype, $entityid, $setfavorite, qa_lang($setfavorite ? 'main/remove_favorites' : 'main/add_favorites')); $favoriteform=qa_favorite_form($entitytype, $entityid, $setfavorite, qa_lang($setfavorite ? 'main/remove_favorites' : 'main/add_favorites'));
$themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-favorite', null, null); $themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-favorite', null, null);
echo "QA_AJAX_RESPONSE\n1\n"; echo "QA_AJAX_RESPONSE\n1\n";
$themeclass->favorite_inner_html($favoriteform); $themeclass->favorite_inner_html($favoriteform);
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-mailing.php File: qa-include/qa-ajax-mailing.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax mailing loop requests Description: Server-side response to Ajax mailing loop requests
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -27,28 +27,28 @@ ...@@ -27,28 +27,28 @@
require_once QA_INCLUDE_DIR.'qa-app-users.php'; require_once QA_INCLUDE_DIR.'qa-app-users.php';
require_once QA_INCLUDE_DIR.'qa-app-mailing.php'; require_once QA_INCLUDE_DIR.'qa-app-mailing.php';
$continue=false; $continue=false;
if (qa_get_logged_in_level()>=QA_USER_LEVEL_ADMIN) { if (qa_get_logged_in_level()>=QA_USER_LEVEL_ADMIN) {
$starttime=time(); $starttime=time();
qa_mailing_perform_step(); qa_mailing_perform_step();
if ($starttime==time()) if ($starttime==time())
sleep(1); // make sure at least one second has passed sleep(1); // make sure at least one second has passed
$message=qa_mailing_progress_message(); $message=qa_mailing_progress_message();
if (isset($message)) if (isset($message))
$continue=true; $continue=true;
else else
$message=qa_lang('admin/mailing_complete'); $message=qa_lang('admin/mailing_complete');
} else } else
$message=qa_lang('admin/no_privileges'); $message=qa_lang('admin/no_privileges');
echo "QA_AJAX_RESPONSE\n".(int)$continue."\n".qa_html($message); echo "QA_AJAX_RESPONSE\n".(int)$continue."\n".qa_html($message);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-notice.php File: qa-include/qa-ajax-notice.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax requests to close a notice Description: Server-side response to Ajax requests to close a notice
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -27,27 +27,27 @@ ...@@ -27,27 +27,27 @@
require_once QA_INCLUDE_DIR.'qa-app-users.php'; require_once QA_INCLUDE_DIR.'qa-app-users.php';
require_once QA_INCLUDE_DIR.'qa-db-notices.php'; require_once QA_INCLUDE_DIR.'qa-db-notices.php';
require_once QA_INCLUDE_DIR.'qa-db-users.php'; require_once QA_INCLUDE_DIR.'qa-db-users.php';
$noticeid=qa_post_text('noticeid');
$noticeid=qa_post_text('noticeid');
if (!qa_check_form_security_code('notice-'.$noticeid, qa_post_text('code'))) if (!qa_check_form_security_code('notice-'.$noticeid, qa_post_text('code')))
echo "QA_AJAX_RESPONSE\n0\n".qa_lang('misc/form_security_reload'); echo "QA_AJAX_RESPONSE\n0\n".qa_lang('misc/form_security_reload');
else { else {
if ($noticeid=='visitor') if ($noticeid=='visitor')
setcookie('qa_noticed', 1, time()+86400*3650, '/', QA_COOKIE_DOMAIN); setcookie('qa_noticed', 1, time()+86400*3650, '/', QA_COOKIE_DOMAIN);
else { else {
$userid=qa_get_logged_in_userid(); $userid=qa_get_logged_in_userid();
if ($noticeid=='welcome') if ($noticeid=='welcome')
qa_db_user_set_flag($userid, QA_USER_FLAGS_WELCOME_NOTICE, false); qa_db_user_set_flag($userid, QA_USER_FLAGS_WELCOME_NOTICE, false);
else else
qa_db_usernotice_delete($userid, $noticeid); qa_db_usernotice_delete($userid, $noticeid);
} }
echo "QA_AJAX_RESPONSE\n1"; echo "QA_AJAX_RESPONSE\n1";
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-recalc.php File: qa-include/qa-ajax-recalc.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax admin recalculation requests Description: Server-side response to Ajax admin recalculation requests
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -26,29 +26,29 @@ ...@@ -26,29 +26,29 @@
require_once QA_INCLUDE_DIR.'qa-app-users.php'; require_once QA_INCLUDE_DIR.'qa-app-users.php';
require_once QA_INCLUDE_DIR.'qa-app-recalc.php'; require_once QA_INCLUDE_DIR.'qa-app-recalc.php';
if (qa_get_logged_in_level()>=QA_USER_LEVEL_ADMIN) { if (qa_get_logged_in_level()>=QA_USER_LEVEL_ADMIN) {
if (!qa_check_form_security_code('admin/recalc', qa_post_text('code'))) { if (!qa_check_form_security_code('admin/recalc', qa_post_text('code'))) {
$state=''; $state='';
$message=qa_lang('misc/form_security_reload'); $message=qa_lang('misc/form_security_reload');
} else { } else {
$state=qa_post_text('state'); $state=qa_post_text('state');
$stoptime=time()+3; $stoptime=time()+3;
while ( qa_recalc_perform_step($state) && (time()<$stoptime) ) while ( qa_recalc_perform_step($state) && (time()<$stoptime) )
; ;
$message=qa_recalc_get_message($state); $message=qa_recalc_get_message($state);
} }
} else { } else {
$state=''; $state='';
$message=qa_lang('admin/no_privileges'); $message=qa_lang('admin/no_privileges');
} }
echo "QA_AJAX_RESPONSE\n1\n".$state."\n".qa_html($message); echo "QA_AJAX_RESPONSE\n1\n".$state."\n".qa_html($message);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-show-comments.php File: qa-include/qa-ajax-show-comments.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax request to view full comment list Description: Server-side response to Ajax request to view full comment list
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -37,31 +37,31 @@ ...@@ -37,31 +37,31 @@
$questionid=qa_post_text('c_questionid'); $questionid=qa_post_text('c_questionid');
$parentid=qa_post_text('c_parentid'); $parentid=qa_post_text('c_parentid');
$userid=qa_get_logged_in_userid(); $userid=qa_get_logged_in_userid();
list($question, $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, $questionid),
qa_db_full_post_selectspec($userid, $parentid), qa_db_full_post_selectspec($userid, $parentid),
qa_db_full_child_posts_selectspec($userid, $parentid) qa_db_full_child_posts_selectspec($userid, $parentid)
); );
if (isset($parent)) { if (isset($parent)) {
$parent=$parent+qa_page_q_post_rules($parent, null, null, $children); $parent=$parent+qa_page_q_post_rules($parent, null, null, $children);
// in theory we should retrieve the parent's parent and siblings for the above, but they're not going to be relevant // in theory we should retrieve the parent's parent and siblings for the above, but they're not going to be relevant
foreach ($children as $key => $child) foreach ($children as $key => $child)
$children[$key]=$child+qa_page_q_post_rules($child, $parent, $children, null); $children[$key]=$child+qa_page_q_post_rules($child, $parent, $children, null);
$usershtml=qa_userids_handles_html($children, true); $usershtml=qa_userids_handles_html($children, true);
qa_sort_by($children, 'created'); qa_sort_by($children, 'created');
$c_list=qa_page_q_comment_follow_list($question, $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); $themeclass=qa_load_theme_class(qa_get_site_theme(), 'ajax-comments', null, null);
echo "QA_AJAX_RESPONSE\n1\n"; echo "QA_AJAX_RESPONSE\n1\n";
// Send back the HTML // Send back the HTML
$themeclass->c_list_items($c_list['cs']); $themeclass->c_list_items($c_list['cs']);
...@@ -69,10 +69,10 @@ ...@@ -69,10 +69,10 @@
return; return;
} }
echo "QA_AJAX_RESPONSE\n0\n"; echo "QA_AJAX_RESPONSE\n0\n";
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
*/ */
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-version.php File: qa-include/qa-ajax-version.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax version check requests Description: Server-side response to Ajax version check requests
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -26,21 +26,21 @@ ...@@ -26,21 +26,21 @@
require_once QA_INCLUDE_DIR.'qa-app-admin.php'; require_once QA_INCLUDE_DIR.'qa-app-admin.php';
$uri=qa_post_text('uri'); $uri=qa_post_text('uri');
$versionkey=qa_post_text('versionkey'); $versionkey=qa_post_text('versionkey');
$urikey=qa_post_text('urikey'); $urikey=qa_post_text('urikey');
$version=qa_post_text('version'); $version=qa_post_text('version');
$metadata=qa_admin_addon_metadata(qa_retrieve_url($uri), array( $metadata=qa_admin_addon_metadata(qa_retrieve_url($uri), array(
'version' => $versionkey, 'version' => $versionkey,
'uri' => $urikey, 'uri' => $urikey,
// these two elements are only present for plugins, not themes, so we can hard code them here // these two elements are only present for plugins, not themes, so we can hard code them here
'min_q2a' => 'Plugin Minimum Question2Answer Version', 'min_q2a' => 'Plugin Minimum Question2Answer Version',
'min_php' => 'Plugin Minimum PHP Version', 'min_php' => 'Plugin Minimum PHP Version',
)); ));
if (strlen(@$metadata['version'])) { if (strlen(@$metadata['version'])) {
if (strcmp($metadata['version'], $version)) { if (strcmp($metadata['version'], $version)) {
if (qa_qa_version_below(@$metadata['min_q2a'])) if (qa_qa_version_below(@$metadata['min_q2a']))
...@@ -57,20 +57,20 @@ ...@@ -57,20 +57,20 @@
else { else {
$response=qa_lang_html_sub('admin/version_get_x', qa_html('v'.$metadata['version'])); $response=qa_lang_html_sub('admin/version_get_x', qa_html('v'.$metadata['version']));
if (strlen(@$metadata['uri'])) if (strlen(@$metadata['uri']))
$response='<a href="'.qa_html($metadata['uri']).'" style="color:#d00;">'.$response.'</a>'; $response='<a href="'.qa_html($metadata['uri']).'" style="color:#d00;">'.$response.'</a>';
} }
} else } else
$response=qa_lang_html('admin/version_latest'); $response=qa_lang_html('admin/version_latest');
} else } else
$response=qa_lang_html('admin/version_latest_unknown'); $response=qa_lang_html('admin/version_latest_unknown');
echo "QA_AJAX_RESPONSE\n1\n".$response; echo "QA_AJAX_RESPONSE\n1\n".$response;
/* /*
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-vote.php File: qa-include/qa-ajax-vote.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax voting requests Description: Server-side response to Ajax voting requests
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -30,32 +30,32 @@ ...@@ -30,32 +30,32 @@
require_once QA_INCLUDE_DIR.'qa-app-format.php'; require_once QA_INCLUDE_DIR.'qa-app-format.php';
require_once QA_INCLUDE_DIR.'qa-app-options.php'; require_once QA_INCLUDE_DIR.'qa-app-options.php';
require_once QA_INCLUDE_DIR.'qa-db-selects.php'; require_once QA_INCLUDE_DIR.'qa-db-selects.php';
$postid=qa_post_text('postid'); $postid=qa_post_text('postid');
$vote=qa_post_text('vote'); $vote=qa_post_text('vote');
$code=qa_post_text('code'); $code=qa_post_text('code');
$userid=qa_get_logged_in_userid(); $userid=qa_get_logged_in_userid();
$cookieid=qa_cookie_get(); $cookieid=qa_cookie_get();
if (!qa_check_form_security_code('vote', $code)) if (!qa_check_form_security_code('vote', $code))
$voteerror=qa_lang_html('misc/form_security_reload'); $voteerror=qa_lang_html('misc/form_security_reload');
else { else {
$post=qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $postid)); $post=qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $postid));
$voteerror=qa_vote_error_html($post, $vote, $userid, qa_request()); $voteerror=qa_vote_error_html($post, $vote, $userid, qa_request());
} }
if ($voteerror===false) { if ($voteerror===false) {
qa_vote_set($post, $userid, qa_get_logged_in_handle(), $cookieid, $vote); qa_vote_set($post, $userid, qa_get_logged_in_handle(), $cookieid, $vote);
$post=qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $postid)); $post=qa_db_select_with_pending(qa_db_full_post_selectspec($userid, $postid));
$fields=qa_post_html_fields($post, $userid, $cookieid, array(), null, array( $fields=qa_post_html_fields($post, $userid, $cookieid, array(), null, array(
'voteview' => qa_get_vote_view($post, 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); $themeclass=qa_load_theme_class(qa_get_site_theme(), 'voting', null, null);
echo "QA_AJAX_RESPONSE\n1\n"; echo "QA_AJAX_RESPONSE\n1\n";
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
} else } else
echo "QA_AJAX_RESPONSE\n0\n".$voteerror; echo "QA_AJAX_RESPONSE\n0\n".$voteerror;
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax-wallpost.php File: qa-include/qa-ajax-wallpost.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Server-side response to Ajax wall post requests Description: Server-side response to Ajax wall post requests
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -23,46 +23,46 @@ ...@@ -23,46 +23,46 @@
More about this license: http://www.question2answer.org/license.php 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-messages.php';
require_once QA_INCLUDE_DIR.'qa-app-users.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-app-cookies.php';
require_once QA_INCLUDE_DIR.'qa-db-selects.php'; require_once QA_INCLUDE_DIR.'qa-db-selects.php';
$message=qa_post_text('message'); $message=qa_post_text('message');
$tohandle=qa_post_text('handle'); $tohandle=qa_post_text('handle');
$morelink=qa_post_text('morelink'); $morelink=qa_post_text('morelink');
$touseraccount=qa_db_select_with_pending(qa_db_user_account_selectspec($tohandle, false)); $touseraccount=qa_db_select_with_pending(qa_db_user_account_selectspec($tohandle, false));
$loginuserid=qa_get_logged_in_userid(); $loginuserid=qa_get_logged_in_userid();
$errorhtml=qa_wall_error_html($loginuserid, $touseraccount['userid'], $touseraccount['flags']); $errorhtml=qa_wall_error_html($loginuserid, $touseraccount['userid'], $touseraccount['flags']);
if ($errorhtml || (!strlen($message)) || !qa_check_form_security_code('wall-'.$tohandle, qa_post_text('code')) ) 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 echo "QA_AJAX_RESPONSE\n0"; // if there's an error, process in non-Ajax way
else { else {
$messageid=qa_wall_add_post($loginuserid, qa_get_logged_in_handle(), qa_cookie_get(), $messageid=qa_wall_add_post($loginuserid, qa_get_logged_in_handle(), qa_cookie_get(),
$touseraccount['userid'], $touseraccount['handle'], $message, ''); $touseraccount['userid'], $touseraccount['handle'], $message, '');
$touseraccount['wallposts']++; // won't have been updated $touseraccount['wallposts']++; // won't have been updated
$usermessages=qa_db_select_with_pending(qa_db_recent_messages_selectspec(null, null, $touseraccount['userid'], true, qa_opt('page_size_wall'))); $usermessages=qa_db_select_with_pending(qa_db_recent_messages_selectspec(null, null, $touseraccount['userid'], true, qa_opt('page_size_wall')));
$usermessages=qa_wall_posts_add_rules($usermessages, 0); $usermessages=qa_wall_posts_add_rules($usermessages, 0);
$themeclass=qa_load_theme_class(qa_get_site_theme(), 'wall', null, null); $themeclass=qa_load_theme_class(qa_get_site_theme(), 'wall', null, null);
echo "QA_AJAX_RESPONSE\n1\n"; echo "QA_AJAX_RESPONSE\n1\n";
echo 'm'.$messageid."\n"; // element in list to be revealed echo 'm'.$messageid."\n"; // element in list to be revealed
foreach ($usermessages as $message) foreach ($usermessages as $message)
$themeclass->message_item(qa_wall_post_view($message)); $themeclass->message_item(qa_wall_post_view($message));
if ($morelink && ($touseraccount['wallposts']>count($usermessages))) if ($morelink && ($touseraccount['wallposts']>count($usermessages)))
$themeclass->message_item(qa_wall_view_more_link($tohandle, count($usermessages))); $themeclass->message_item(qa_wall_view_more_link($tohandle, count($usermessages)));
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-ajax.php File: qa-include/qa-ajax.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Front line of response to Ajax requests, routing as appropriate Description: Front line of response to Ajax requests, routing as appropriate
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -39,14 +39,14 @@ ...@@ -39,14 +39,14 @@
require 'qa-base.php'; require 'qa-base.php';
qa_report_process_stage('init_ajax'); qa_report_process_stage('init_ajax');
// Get general Ajax parameters from the POST payload, and clear $_GET // Get general Ajax parameters from the POST payload, and clear $_GET
qa_set_request(qa_post_text('qa_request'), qa_post_text('qa_root')); qa_set_request(qa_post_text('qa_request'), qa_post_text('qa_root'));
$_GET=array(); // for qa_self_html() $_GET=array(); // for qa_self_html()
// Database failure handler // Database failure handler
...@@ -77,14 +77,14 @@ ...@@ -77,14 +77,14 @@
'wallpost' => 'qa-ajax-wallpost.php', 'wallpost' => 'qa-ajax-wallpost.php',
'click_wall' => 'qa-ajax-click-wall.php', 'click_wall' => 'qa-ajax-click-wall.php',
); );
$operation=qa_post_text('qa_operation'); $operation=qa_post_text('qa_operation');
if (isset($routing[$operation])) { if (isset($routing[$operation])) {
qa_db_connect('qa_ajax_db_fail_handler'); qa_db_connect('qa_ajax_db_fail_handler');
require QA_INCLUDE_DIR.$routing[$operation]; require QA_INCLUDE_DIR.$routing[$operation];
qa_db_disconnect(); qa_db_disconnect();
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-blobs.php File: qa-include/qa-app-blobs.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Application-level blob-management functions Description: Application-level blob-management functions
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -29,18 +29,18 @@ ...@@ -29,18 +29,18 @@
exit; exit;
} }
function qa_get_blob_url($blobid, $absolute=false) function qa_get_blob_url($blobid, $absolute=false)
/* /*
Return the URL which will output $blobid from the database when requested, $absolute or relative Return the URL which will output $blobid from the database when requested, $absolute or relative
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return qa_path('blob', array('qa_blobid' => $blobid), $absolute ? qa_opt('site_url') : null, QA_URL_FORMAT_PARAMS); return qa_path('blob', array('qa_blobid' => $blobid), $absolute ? qa_opt('site_url') : null, QA_URL_FORMAT_PARAMS);
} }
function qa_get_blob_directory($blobid) function qa_get_blob_directory($blobid)
/* /*
Return the full path to the on-disk directory for blob $blobid (subdirectories are named by the first 3 digits of $blobid) Return the full path to the on-disk directory for blob $blobid (subdirectories are named by the first 3 digits of $blobid)
...@@ -50,8 +50,8 @@ ...@@ -50,8 +50,8 @@
return rtrim(QA_BLOBS_DIRECTORY, '/').'/'.substr(str_pad($blobid, 20, '0', STR_PAD_LEFT), 0, 3); return rtrim(QA_BLOBS_DIRECTORY, '/').'/'.substr(str_pad($blobid, 20, '0', STR_PAD_LEFT), 0, 3);
} }
function qa_get_blob_filename($blobid, $format) function qa_get_blob_filename($blobid, $format)
/* /*
Return the full page and filename of blob $blobid which is in $format ($format is used as the file name suffix e.g. .jpg) Return the full page and filename of blob $blobid which is in $format ($format is used as the file name suffix e.g. .jpg)
...@@ -61,8 +61,8 @@ ...@@ -61,8 +61,8 @@
return qa_get_blob_directory($blobid).'/'.$blobid.'.'.preg_replace('/[^A-Za-z0-9]/', '', $format); 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) function qa_create_blob($content, $format, $sourcefilename=null, $userid=null, $cookieid=null, $ip=null)
/* /*
Create a new blob (storing the content in the database or on disk as appropriate) with $content and $format, returning its blobid. Create a new blob (storing the content in the database or on disk as appropriate) with $content and $format, returning its blobid.
...@@ -70,9 +70,9 @@ ...@@ -70,9 +70,9 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-db-blobs.php'; 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); $blobid=qa_db_blob_create(defined('QA_BLOBS_DIRECTORY') ? null : $content, $format, $sourcefilename, $userid, $cookieid, $ip);
if (isset($blobid) && defined('QA_BLOBS_DIRECTORY')) if (isset($blobid) && defined('QA_BLOBS_DIRECTORY'))
...@@ -81,8 +81,8 @@ ...@@ -81,8 +81,8 @@
return $blobid; return $blobid;
} }
function qa_write_blob_file($blobid, $content, $format) function qa_write_blob_file($blobid, $content, $format)
/* /*
Write the on-disk file for blob $blobid with $content and $format. Returns true if the write succeeded, false otherwise. Write the on-disk file for blob $blobid with $content and $format. Returns true if the write succeeded, false otherwise.
...@@ -91,45 +91,45 @@ ...@@ -91,45 +91,45 @@
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$written=false; $written=false;
$directory=qa_get_blob_directory($blobid); $directory=qa_get_blob_directory($blobid);
if (is_dir($directory) || mkdir($directory, fileperms(rtrim(QA_BLOBS_DIRECTORY, '/')) & 0777)) { if (is_dir($directory) || mkdir($directory, fileperms(rtrim(QA_BLOBS_DIRECTORY, '/')) & 0777)) {
$filename=qa_get_blob_filename($blobid, $format); $filename=qa_get_blob_filename($blobid, $format);
$file=fopen($filename, 'xb'); $file=fopen($filename, 'xb');
if (is_resource($file)) { if (is_resource($file)) {
if (fwrite($file, $content)>=strlen($content)) if (fwrite($file, $content)>=strlen($content))
$written=true; $written=true;
fclose($file); fclose($file);
if (!$written) if (!$written)
unlink($filename); unlink($filename);
} }
} }
return $written; return $written;
} }
function qa_read_blob($blobid) function qa_read_blob($blobid)
/* /*
Retrieve blob $blobid from the database, reading the content from disk if appropriate Retrieve blob $blobid from the database, reading the content from disk if appropriate
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-db-blobs.php'; require_once QA_INCLUDE_DIR.'qa-db-blobs.php';
$blob=qa_db_blob_read($blobid); $blob=qa_db_blob_read($blobid);
if (defined('QA_BLOBS_DIRECTORY') && !isset($blob['content'])) if (defined('QA_BLOBS_DIRECTORY') && !isset($blob['content']))
$blob['content']=qa_read_blob_file($blobid, $blob['format']); $blob['content']=qa_read_blob_file($blobid, $blob['format']);
return $blob; return $blob;
} }
function qa_read_blob_file($blobid, $format) function qa_read_blob_file($blobid, $format)
/* /*
Read the content of blob $blobid in $format from disk. On failure, it will return false. Read the content of blob $blobid in $format from disk. On failure, it will return false.
...@@ -139,39 +139,39 @@ ...@@ -139,39 +139,39 @@
return file_get_contents(qa_get_blob_filename($blobid, $format)); return file_get_contents(qa_get_blob_filename($blobid, $format));
} }
function qa_delete_blob($blobid) function qa_delete_blob($blobid)
/* /*
Delete blob $blobid from the database, and remove the on-disk file if appropriate Delete blob $blobid from the database, and remove the on-disk file if appropriate
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-db-blobs.php'; require_once QA_INCLUDE_DIR.'qa-db-blobs.php';
if (defined('QA_BLOBS_DIRECTORY')) { if (defined('QA_BLOBS_DIRECTORY')) {
$blob=qa_db_blob_read($blobid); $blob=qa_db_blob_read($blobid);
if (isset($blob) && !isset($blob['content'])) if (isset($blob) && !isset($blob['content']))
unlink(qa_get_blob_filename($blobid, $blob['format'])); unlink(qa_get_blob_filename($blobid, $blob['format']));
} }
qa_db_blob_delete($blobid); qa_db_blob_delete($blobid);
} }
function qa_delete_blob_file($blobid, $format) function qa_delete_blob_file($blobid, $format)
/* /*
Delete the on-disk file for blob $blobid in $format Delete the on-disk file for blob $blobid in $format
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
unlink(qa_get_blob_filename($blobid, $format)); unlink(qa_get_blob_filename($blobid, $format));
} }
function qa_blob_exists($blobid) function qa_blob_exists($blobid)
/* /*
Check if blob $blobid exists Check if blob $blobid exists
...@@ -180,10 +180,10 @@ ...@@ -180,10 +180,10 @@
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-db-blobs.php'; require_once QA_INCLUDE_DIR.'qa-db-blobs.php';
return qa_db_blob_exists($blobid); return qa_db_blob_exists($blobid);
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-captcha.php File: qa-include/qa-app-captcha.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Wrapper functions and utilities for captcha modules Description: Wrapper functions and utilities for captcha modules
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -36,32 +36,32 @@ ...@@ -36,32 +36,32 @@
*/ */
{ {
$module=qa_load_module('captcha', qa_opt('captcha_module')); $module=qa_load_module('captcha', qa_opt('captcha_module'));
return isset($module) && ( (!method_exists($module, 'allow_captcha')) || $module->allow_captcha()); return isset($module) && ( (!method_exists($module, 'allow_captcha')) || $module->allow_captcha());
} }
function qa_captcha_reason_note($captchareason) function qa_captcha_reason_note($captchareason)
/* /*
Return an HTML string explaining $captchareason (from qa_user_captcha_reason()) to the user about why they are seeing a captcha Return an HTML string explaining $captchareason (from qa_user_captcha_reason()) to the user about why they are seeing a captcha
*/ */
{ {
$notehtml=null; $notehtml=null;
switch ($captchareason) { switch ($captchareason) {
case 'login': case 'login':
$notehtml=qa_insert_login_links(qa_lang_html('misc/captcha_login_fix')); $notehtml=qa_insert_login_links(qa_lang_html('misc/captcha_login_fix'));
break; break;
case 'confirm': case 'confirm':
$notehtml=qa_insert_login_links(qa_lang_html('misc/captcha_confirm_fix')); $notehtml=qa_insert_login_links(qa_lang_html('misc/captcha_confirm_fix'));
break; break;
case 'approve': case 'approve':
$notehtml=qa_lang_html('misc/captcha_approve_fix'); $notehtml=qa_lang_html('misc/captcha_approve_fix');
break; break;
} }
return $notehtml; return $notehtml;
} }
...@@ -73,16 +73,16 @@ ...@@ -73,16 +73,16 @@
{ {
if (qa_captcha_available()) { if (qa_captcha_available()) {
$captcha=qa_load_module('captcha', qa_opt('captcha_module')); $captcha=qa_load_module('captcha', qa_opt('captcha_module'));
$count=@++$qa_content['qa_captcha_count']; // work around fact that reCAPTCHA can only display per page $count=@++$qa_content['qa_captcha_count']; // work around fact that reCAPTCHA can only display per page
if ($count>1) if ($count>1)
$html='[captcha placeholder]'; // single captcha will be moved about the page, to replace this $html='[captcha placeholder]'; // single captcha will be moved about the page, to replace this
else { else {
$qa_content['script_var']['qa_captcha_in']='qa_captcha_div_1'; $qa_content['script_var']['qa_captcha_in']='qa_captcha_div_1';
$html=$captcha->form_html($qa_content, @$errors['captcha']); $html=$captcha->form_html($qa_content, @$errors['captcha']);
} }
$fields['captcha']=array( $fields['captcha']=array(
'type' => 'custom', 'type' => 'custom',
'label' => qa_lang_html('misc/captcha_label'), 'label' => qa_lang_html('misc/captcha_label'),
...@@ -90,10 +90,10 @@ ...@@ -90,10 +90,10 @@
'error' => @array_key_exists('captcha', $errors) ? qa_lang_html('misc/captcha_error') : null, 'error' => @array_key_exists('captcha', $errors) ? qa_lang_html('misc/captcha_error') : null,
'note' => $note, 'note' => $note,
); );
return "if (qa_captcha_in!='qa_captcha_div_".$count."') { document.getElementById('qa_captcha_div_".$count."').innerHTML=document.getElementById(qa_captcha_in).innerHTML; document.getElementById(qa_captcha_in).innerHTML=''; qa_captcha_in='qa_captcha_div_".$count."'; }"; return "if (qa_captcha_in!='qa_captcha_div_".$count."') { document.getElementById('qa_captcha_div_".$count."').innerHTML=document.getElementById(qa_captcha_in).innerHTML; document.getElementById(qa_captcha_in).innerHTML=''; qa_captcha_in='qa_captcha_div_".$count."'; }";
} }
return ''; return '';
} }
...@@ -105,13 +105,13 @@ ...@@ -105,13 +105,13 @@
{ {
if (qa_captcha_available()) { if (qa_captcha_available()) {
$captcha=qa_load_module('captcha', qa_opt('captcha_module')); $captcha=qa_load_module('captcha', qa_opt('captcha_module'));
if (!$captcha->validate_post($error)) { if (!$captcha->validate_post($error)) {
$errors['captcha']=$error; $errors['captcha']=$error;
return false; return false;
} }
} }
return true; return true;
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-cookies.php File: qa-include/qa-app-cookies.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: User cookie management (application level) for tracking anonymous posts Description: User cookie management (application level) for tracking anonymous posts
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -36,11 +36,11 @@ ...@@ -36,11 +36,11 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return isset($_COOKIE['qa_id']) ? qa_gpc_to_string($_COOKIE['qa_id']) : null; return isset($_COOKIE['qa_id']) ? qa_gpc_to_string($_COOKIE['qa_id']) : null;
} }
function qa_cookie_get_create() function qa_cookie_get_create()
/* /*
Return user identification cookie sent by browser if valid, or create a new one if not. Return user identification cookie sent by browser if valid, or create a new one if not.
...@@ -48,23 +48,23 @@ ...@@ -48,23 +48,23 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-db-cookies.php'; require_once QA_INCLUDE_DIR.'qa-db-cookies.php';
$cookieid=qa_cookie_get(); $cookieid=qa_cookie_get();
if (isset($cookieid) && qa_db_cookie_exists($cookieid)) if (isset($cookieid) && qa_db_cookie_exists($cookieid))
; // cookie is valid ; // cookie is valid
else else
$cookieid=qa_db_cookie_create(qa_remote_ip_address()); $cookieid=qa_db_cookie_create(qa_remote_ip_address());
setcookie('qa_id', $cookieid, time()+86400*365, '/', QA_COOKIE_DOMAIN); setcookie('qa_id', $cookieid, time()+86400*365, '/', QA_COOKIE_DOMAIN);
$_COOKIE['qa_id']=$cookieid; $_COOKIE['qa_id']=$cookieid;
return $cookieid; return $cookieid;
} }
function qa_cookie_report_action($cookieid, $action) function qa_cookie_report_action($cookieid, $action)
/* /*
Called after a database write $action performed by a user identified by $cookieid, Called after a database write $action performed by a user identified by $cookieid,
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
*/ */
{ {
require_once QA_INCLUDE_DIR.'qa-db-cookies.php'; require_once QA_INCLUDE_DIR.'qa-db-cookies.php';
qa_db_cookie_written($cookieid, qa_remote_ip_address()); qa_db_cookie_written($cookieid, qa_remote_ip_address());
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-emails.php File: qa-include/qa-app-emails.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Wrapper functions for sending email notifications to users Description: Wrapper functions for sending email notifications to users
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -39,11 +39,11 @@ ...@@ -39,11 +39,11 @@
*/ */
{ {
global $qa_notifications_suspended; global $qa_notifications_suspended;
$qa_notifications_suspended+=($suspend ? 1 : -1); $qa_notifications_suspended+=($suspend ? 1 : -1);
} }
function qa_send_notification($userid, $email, $handle, $subject, $body, $subs) function qa_send_notification($userid, $email, $handle, $subject, $body, $subs)
/* /*
Send email to person with $userid and/or $email and/or $handle (null/invalid values are ignored or retrieved from Send email to person with $userid and/or $email and/or $handle (null/invalid values are ignored or retrieved from
...@@ -52,50 +52,50 @@ ...@@ -52,50 +52,50 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
global $qa_notifications_suspended; global $qa_notifications_suspended;
if ($qa_notifications_suspended>0) if ($qa_notifications_suspended>0)
return false; return false;
require_once QA_INCLUDE_DIR.'qa-db-selects.php'; require_once QA_INCLUDE_DIR.'qa-db-selects.php';
require_once QA_INCLUDE_DIR.'qa-util-string.php'; require_once QA_INCLUDE_DIR.'qa-util-string.php';
if (isset($userid)) { if (isset($userid)) {
$needemail=!qa_email_validate(@$email); // take from user if invalid, e.g. @ used in practice $needemail=!qa_email_validate(@$email); // take from user if invalid, e.g. @ used in practice
$needhandle=empty($handle); $needhandle=empty($handle);
if ($needemail || $needhandle) { if ($needemail || $needhandle) {
if (QA_FINAL_EXTERNAL_USERS) { if (QA_FINAL_EXTERNAL_USERS) {
if ($needhandle) { if ($needhandle) {
$handles=qa_get_public_from_userids(array($userid)); $handles=qa_get_public_from_userids(array($userid));
$handle=@$handles[$userid]; $handle=@$handles[$userid];
} }
if ($needemail) if ($needemail)
$email=qa_get_user_email($userid); $email=qa_get_user_email($userid);
} else { } else {
$useraccount=qa_db_select_with_pending( $useraccount=qa_db_select_with_pending(
qa_db_user_account_selectspec($userid, true) qa_db_user_account_selectspec($userid, true)
); );
if ($needhandle) if ($needhandle)
$handle=@$useraccount['handle']; $handle=@$useraccount['handle'];
if ($needemail) if ($needemail)
$email=@$useraccount['email']; $email=@$useraccount['email'];
} }
} }
} }
if (isset($email) && qa_email_validate($email)) { if (isset($email) && qa_email_validate($email)) {
$subs['^site_title']=qa_opt('site_title'); $subs['^site_title']=qa_opt('site_title');
$subs['^handle']=$handle; $subs['^handle']=$handle;
$subs['^email']=$email; $subs['^email']=$email;
$subs['^open']="\n"; $subs['^open']="\n";
$subs['^close']="\n"; $subs['^close']="\n";
return qa_send_email(array( return qa_send_email(array(
'fromemail' => qa_opt('from_email'), 'fromemail' => qa_opt('from_email'),
'fromname' => qa_opt('site_title'), 'fromname' => qa_opt('site_title'),
...@@ -105,11 +105,11 @@ ...@@ -105,11 +105,11 @@
'body' => (empty($handle) ? '' : qa_lang_sub('emails/to_handle_prefix', $handle)).strtr($body, $subs), 'body' => (empty($handle) ? '' : qa_lang_sub('emails/to_handle_prefix', $handle)).strtr($body, $subs),
'html' => false, 'html' => false,
)); ));
} else } else
return false; return false;
} }
function qa_send_email($params) function qa_send_email($params)
/* /*
...@@ -118,14 +118,14 @@ ...@@ -118,14 +118,14 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
// @error_log(print_r($params, true)); // @error_log(print_r($params, true));
require_once QA_INCLUDE_DIR.'qa-class.phpmailer.php'; require_once QA_INCLUDE_DIR.'qa-class.phpmailer.php';
$mailer=new PHPMailer(); $mailer=new PHPMailer();
$mailer->CharSet='utf-8'; $mailer->CharSet='utf-8';
$mailer->From=$params['fromemail']; $mailer->From=$params['fromemail'];
$mailer->Sender=$params['fromemail']; $mailer->Sender=$params['fromemail'];
$mailer->FromName=$params['fromname']; $mailer->FromName=$params['fromname'];
...@@ -135,22 +135,22 @@ ...@@ -135,22 +135,22 @@
if ($params['html']) if ($params['html'])
$mailer->IsHTML(true); $mailer->IsHTML(true);
if (qa_opt('smtp_active')) { if (qa_opt('smtp_active')) {
$mailer->IsSMTP(); $mailer->IsSMTP();
$mailer->Host=qa_opt('smtp_address'); $mailer->Host=qa_opt('smtp_address');
$mailer->Port=qa_opt('smtp_port'); $mailer->Port=qa_opt('smtp_port');
if (qa_opt('smtp_secure')) if (qa_opt('smtp_secure'))
$mailer->SMTPSecure=qa_opt('smtp_secure'); $mailer->SMTPSecure=qa_opt('smtp_secure');
if (qa_opt('smtp_authenticate')) { if (qa_opt('smtp_authenticate')) {
$mailer->SMTPAuth=true; $mailer->SMTPAuth=true;
$mailer->Username=qa_opt('smtp_username'); $mailer->Username=qa_opt('smtp_username');
$mailer->Password=qa_opt('smtp_password'); $mailer->Password=qa_opt('smtp_password');
} }
} }
return $mailer->Send(); return $mailer->Send();
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-events.php File: qa-include/qa-app-events.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Handles the submission of events to the database (application level) Description: Handles the submission of events to the database (application level)
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
require_once QA_INCLUDE_DIR.'qa-db-events.php'; require_once QA_INCLUDE_DIR.'qa-db-events.php';
require_once QA_INCLUDE_DIR.'qa-app-updates.php'; require_once QA_INCLUDE_DIR.'qa-app-updates.php';
function qa_create_event_for_q_user($questionid, $lastpostid, $updatetype, $lastuserid, $otheruserid=null, $timestamp=null) function qa_create_event_for_q_user($questionid, $lastpostid, $updatetype, $lastuserid, $otheruserid=null, $timestamp=null)
/* /*
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
if (isset($otheruserid) && ($otheruserid!=$lastuserid)) if (isset($otheruserid) && ($otheruserid!=$lastuserid))
qa_db_event_create_not_entity($otheruserid, $questionid, $lastpostid, $updatetype, $lastuserid, $timestamp); // possible other user to be informed qa_db_event_create_not_entity($otheruserid, $questionid, $lastpostid, $updatetype, $lastuserid, $timestamp); // possible other user to be informed
} }
function qa_create_event_for_tags($tagstring, $questionid, $updatetype, $lastuserid, $timestamp=null) function qa_create_event_for_tags($tagstring, $questionid, $updatetype, $lastuserid, $timestamp=null)
/* /*
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
foreach ($tagwordids as $wordid) foreach ($tagwordids as $wordid)
qa_db_event_create_for_entity(QA_ENTITY_TAG, $wordid, $questionid, $questionid, $updatetype, $lastuserid, $timestamp); qa_db_event_create_for_entity(QA_ENTITY_TAG, $wordid, $questionid, $questionid, $updatetype, $lastuserid, $timestamp);
} }
function qa_create_event_for_category($categoryid, $questionid, $updatetype, $lastuserid, $timestamp=null) function qa_create_event_for_category($categoryid, $questionid, $updatetype, $lastuserid, $timestamp=null)
/* /*
...@@ -79,14 +79,14 @@ ...@@ -79,14 +79,14 @@
if (isset($categoryid)) { if (isset($categoryid)) {
require_once QA_INCLUDE_DIR.'qa-db-selects.php'; 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-format.php';
$categories=qa_category_path(qa_db_single_select(qa_db_category_nav_selectspec($categoryid, true)), $categoryid); $categories=qa_category_path(qa_db_single_select(qa_db_category_nav_selectspec($categoryid, true)), $categoryid);
foreach ($categories as $category) foreach ($categories as $category)
qa_db_event_create_for_entity(QA_ENTITY_CATEGORY, $category['categoryid'], $questionid, $questionid, $updatetype, $lastuserid, $timestamp); qa_db_event_create_for_entity(QA_ENTITY_CATEGORY, $category['categoryid'], $questionid, $questionid, $updatetype, $lastuserid, $timestamp);
} }
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
*/ */
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-favorites.php File: qa-include/qa-app-favorites.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Handles favoriting and unfavoriting (application level) Description: Handles favoriting and unfavoriting (application level)
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -39,42 +39,42 @@ ...@@ -39,42 +39,42 @@
require_once QA_INCLUDE_DIR.'qa-db-favorites.php'; require_once QA_INCLUDE_DIR.'qa-db-favorites.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php'; require_once QA_INCLUDE_DIR.'qa-app-limits.php';
require_once QA_INCLUDE_DIR.'qa-app-updates.php'; require_once QA_INCLUDE_DIR.'qa-app-updates.php';
if ($favorite) if ($favorite)
qa_db_favorite_create($userid, $entitytype, $entityid); qa_db_favorite_create($userid, $entitytype, $entityid);
else else
qa_db_favorite_delete($userid, $entitytype, $entityid); qa_db_favorite_delete($userid, $entitytype, $entityid);
switch ($entitytype) { switch ($entitytype) {
case QA_ENTITY_QUESTION: case QA_ENTITY_QUESTION:
$action=$favorite ? 'q_favorite' : 'q_unfavorite'; $action=$favorite ? 'q_favorite' : 'q_unfavorite';
$params=array('postid' => $entityid); $params=array('postid' => $entityid);
break; break;
case QA_ENTITY_USER: case QA_ENTITY_USER:
$action=$favorite ? 'u_favorite' : 'u_unfavorite'; $action=$favorite ? 'u_favorite' : 'u_unfavorite';
$params=array('userid' => $entityid); $params=array('userid' => $entityid);
break; break;
case QA_ENTITY_TAG: case QA_ENTITY_TAG:
$action=$favorite ? 'tag_favorite' : 'tag_unfavorite'; $action=$favorite ? 'tag_favorite' : 'tag_unfavorite';
$params=array('wordid' => $entityid); $params=array('wordid' => $entityid);
break; break;
case QA_ENTITY_CATEGORY: case QA_ENTITY_CATEGORY:
$action=$favorite ? 'cat_favorite' : 'cat_unfavorite'; $action=$favorite ? 'cat_favorite' : 'cat_unfavorite';
$params=array('categoryid' => $entityid); $params=array('categoryid' => $entityid);
break; break;
default: default:
qa_fatal_error('Favorite type not recognized'); qa_fatal_error('Favorite type not recognized');
break; break;
} }
qa_report_event($action, $userid, $handle, $cookieid, $params); qa_report_event($action, $userid, $handle, $cookieid, $params);
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
*/ */
\ No newline at end of file
<?php <?php
/* /*
Question2Answer (c) Gideon Greenspan Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-limits.php File: qa-include/qa-app-limits.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Monitoring and rate-limiting user actions (application level) Description: Monitoring and rate-limiting user actions (application level)
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
define('QA_LIMIT_MESSAGES', 'M'); // i.e. private messages define('QA_LIMIT_MESSAGES', 'M'); // i.e. private messages
define('QA_LIMIT_WALL_POSTS', 'W'); define('QA_LIMIT_WALL_POSTS', 'W');
function qa_user_limits_remaining($action) function qa_user_limits_remaining($action)
/* /*
Return how many more times the logged in user (and requesting IP address) can perform $action this hour, Return how many more times the logged in user (and requesting IP address) can perform $action this hour,
...@@ -50,11 +50,11 @@ ...@@ -50,11 +50,11 @@
{ {
$userlimits=qa_db_get_pending_result('userlimits', qa_db_user_limits_selectspec(qa_get_logged_in_userid())); $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())); $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]); return qa_limits_calc_remaining($action, @$userlimits[$action], @$iplimits[$action]);
} }
function qa_limits_remaining($userid, $action) function qa_limits_remaining($userid, $action)
/* /*
Return how many more times user $userid and/or the requesting IP can perform $action this hour, where $action is one Return how many more times user $userid and/or the requesting IP can perform $action this hour, where $action is one
...@@ -62,15 +62,15 @@ ...@@ -62,15 +62,15 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-db-limits.php'; require_once QA_INCLUDE_DIR.'qa-db-limits.php';
$dblimits=qa_db_limits_get($userid, qa_remote_ip_address(), $action); $dblimits=qa_db_limits_get($userid, qa_remote_ip_address(), $action);
return qa_limits_calc_remaining($action, @$dblimits['user'], @$dblimits['ip']); return qa_limits_calc_remaining($action, @$dblimits['user'], @$dblimits['ip']);
} }
function qa_limits_calc_remaining($action, $userlimits, $iplimits) function qa_limits_calc_remaining($action, $userlimits, $iplimits)
/* /*
Calculate how many more times $action can be performed this hour, based on $userlimits and $iplimits retrieved from the database Calculate how many more times $action can be performed this hour, based on $userlimits and $iplimits retrieved from the database
...@@ -81,12 +81,12 @@ ...@@ -81,12 +81,12 @@
$usermax=qa_opt('max_rate_user_qs'); $usermax=qa_opt('max_rate_user_qs');
$ipmax=qa_opt('max_rate_ip_qs'); $ipmax=qa_opt('max_rate_ip_qs');
break; break;
case QA_LIMIT_ANSWERS: case QA_LIMIT_ANSWERS:
$usermax=qa_opt('max_rate_user_as'); $usermax=qa_opt('max_rate_user_as');
$ipmax=qa_opt('max_rate_ip_as'); $ipmax=qa_opt('max_rate_ip_as');
break; break;
case QA_LIMIT_COMMENTS: case QA_LIMIT_COMMENTS:
$usermax=qa_opt('max_rate_user_cs'); $usermax=qa_opt('max_rate_user_cs');
$ipmax=qa_opt('max_rate_ip_cs'); $ipmax=qa_opt('max_rate_ip_cs');
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
$usermax=qa_opt('max_rate_user_votes'); $usermax=qa_opt('max_rate_user_votes');
$ipmax=qa_opt('max_rate_ip_votes'); $ipmax=qa_opt('max_rate_ip_votes');
break; break;
case QA_LIMIT_REGISTRATIONS: case QA_LIMIT_REGISTRATIONS:
$usermax=1; // not really relevant $usermax=1; // not really relevant
$ipmax=qa_opt('max_rate_ip_registers'); $ipmax=qa_opt('max_rate_ip_registers');
...@@ -106,28 +106,28 @@ ...@@ -106,28 +106,28 @@
$usermax=1; // not really relevant $usermax=1; // not really relevant
$ipmax=qa_opt('max_rate_ip_logins'); $ipmax=qa_opt('max_rate_ip_logins');
break; break;
case QA_LIMIT_UPLOADS: case QA_LIMIT_UPLOADS:
$usermax=qa_opt('max_rate_user_uploads'); $usermax=qa_opt('max_rate_user_uploads');
$ipmax=qa_opt('max_rate_ip_uploads'); $ipmax=qa_opt('max_rate_ip_uploads');
break; break;
case QA_LIMIT_FLAGS: case QA_LIMIT_FLAGS:
$usermax=qa_opt('max_rate_user_flags'); $usermax=qa_opt('max_rate_user_flags');
$ipmax=qa_opt('max_rate_ip_flags'); $ipmax=qa_opt('max_rate_ip_flags');
break; break;
case QA_LIMIT_MESSAGES: case QA_LIMIT_MESSAGES:
case QA_LIMIT_WALL_POSTS: case QA_LIMIT_WALL_POSTS:
$usermax=qa_opt('max_rate_user_messages'); $usermax=qa_opt('max_rate_user_messages');
$ipmax=qa_opt('max_rate_ip_messages'); $ipmax=qa_opt('max_rate_ip_messages');
break; break;
default: default:
qa_fatal_error('Unknown limit code in qa_limits_calc_remaining: '.$action); qa_fatal_error('Unknown limit code in qa_limits_calc_remaining: '.$action);
break; break;
} }
$period=(int)(qa_opt('db_time')/3600); $period=(int)(qa_opt('db_time')/3600);
return max(0, min( return max(0, min(
...@@ -135,36 +135,36 @@ ...@@ -135,36 +135,36 @@
$ipmax-((@$iplimits['period']==$period) ? $iplimits['count'] : 0) $ipmax-((@$iplimits['period']==$period) ? $iplimits['count'] : 0)
)); ));
} }
function qa_is_ip_blocked() function qa_is_ip_blocked()
/* /*
Return whether the requesting IP address has been blocked from write operations Return whether the requesting IP address has been blocked from write operations
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$blockipclauses=qa_block_ips_explode(qa_opt('block_ips_write')); $blockipclauses=qa_block_ips_explode(qa_opt('block_ips_write'));
foreach ($blockipclauses as $blockipclause) foreach ($blockipclauses as $blockipclause)
if (qa_block_ip_match(qa_remote_ip_address(), $blockipclause)) if (qa_block_ip_match(qa_remote_ip_address(), $blockipclause))
return true; return true;
return false; return false;
} }
function qa_block_ips_explode($blockipstring) function qa_block_ips_explode($blockipstring)
/* /*
Return an array of the clauses within $blockipstring, each of which can contain hyphens or asterisks Return an array of the clauses within $blockipstring, each of which can contain hyphens or asterisks
*/ */
{ {
$blockipstring=preg_replace('/\s*\-\s*/', '-', $blockipstring); // special case for 'x.x.x.x - x.x.x.x' $blockipstring=preg_replace('/\s*\-\s*/', '-', $blockipstring); // special case for 'x.x.x.x - x.x.x.x'
return preg_split('/[^0-9\.\-\*]/', $blockipstring, -1, PREG_SPLIT_NO_EMPTY); return preg_split('/[^0-9\.\-\*]/', $blockipstring, -1, PREG_SPLIT_NO_EMPTY);
} }
function qa_block_ip_match($ip, $blockipclause) function qa_block_ip_match($ip, $blockipclause)
/* /*
Returns whether the ip address $ip is matched by the clause $blockipclause, which can contain a hyphen or asterisk Returns whether the ip address $ip is matched by the clause $blockipclause, which can contain a hyphen or asterisk
...@@ -176,26 +176,26 @@ ...@@ -176,26 +176,26 @@
$iplong=sprintf('%u', ip2long($ip)); $iplong=sprintf('%u', ip2long($ip));
$end1long=sprintf('%u', ip2long($matches[1])); $end1long=sprintf('%u', ip2long($matches[1]));
$end2long=sprintf('%u', ip2long($matches[2])); $end2long=sprintf('%u', ip2long($matches[2]));
return (($iplong>=$end1long) && ($iplong<=$end2long)) || (($iplong>=$end2long) && ($iplong<=$end1long)); return (($iplong>=$end1long) && ($iplong<=$end2long)) || (($iplong>=$end2long) && ($iplong<=$end1long));
} }
} elseif (strlen($blockipclause)) } elseif (strlen($blockipclause))
return preg_match('/^'.str_replace('\\*', '[0-9]+', preg_quote($blockipclause, '/')).'$/', $ip) > 0; return preg_match('/^'.str_replace('\\*', '[0-9]+', preg_quote($blockipclause, '/')).'$/', $ip) > 0;
// preg_quote misses hyphens but that is OK here // preg_quote misses hyphens but that is OK here
} }
return false; return false;
} }
function qa_report_write_action($userid, $cookieid, $action, $questionid, $answerid, $commentid) function qa_report_write_action($userid, $cookieid, $action, $questionid, $answerid, $commentid)
/* /*
Called after a database write $action performed by a user identified by $userid and/or $cookieid. Called after a database write $action performed by a user identified by $userid and/or $cookieid.
*/ */
{} {}
function qa_limits_increment($userid, $action) function qa_limits_increment($userid, $action)
/* /*
Take note for rate limits that user $userid and/or the requesting IP just performed $action, Take note for rate limits that user $userid and/or the requesting IP just performed $action,
...@@ -203,14 +203,14 @@ ...@@ -203,14 +203,14 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-db-limits.php'; require_once QA_INCLUDE_DIR.'qa-db-limits.php';
$period=(int)(qa_opt('db_time')/3600); $period=(int)(qa_opt('db_time')/3600);
if (isset($userid)) if (isset($userid))
qa_db_limits_user_add($userid, $action, $period, 1); qa_db_limits_user_add($userid, $action, $period, 1);
qa_db_limits_ip_add(qa_remote_ip_address(), $action, $period, 1); qa_db_limits_ip_add(qa_remote_ip_address(), $action, $period, 1);
} }
......
<?php <?php
/* /*
Question2Answer (c) Gideon Greenspan Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-mailing.php File: qa-include/qa-app-mailing.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Functions for sending a mailing to all users Description: Functions for sending a mailing to all users
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
*/ */
{ {
require_once QA_INCLUDE_DIR.'qa-db-admin.php'; require_once QA_INCLUDE_DIR.'qa-db-admin.php';
if (strlen(qa_opt('mailing_last_userid'))==0) { if (strlen(qa_opt('mailing_last_userid'))==0) {
qa_opt('mailing_last_timestamp', time()); qa_opt('mailing_last_timestamp', time());
qa_opt('mailing_last_userid', '0'); qa_opt('mailing_last_userid', '0');
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
} }
} }
function qa_mailing_stop() function qa_mailing_stop()
/* /*
Stop a mailing to all users Stop a mailing to all users
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
qa_opt('mailing_total_users', ''); qa_opt('mailing_total_users', '');
} }
function qa_mailing_perform_step() function qa_mailing_perform_step()
/* /*
Allow the mailing to proceed forwards, for the appropriate amount of time and users, based on the options Allow the mailing to proceed forwards, for the appropriate amount of time and users, based on the options
...@@ -66,39 +66,39 @@ ...@@ -66,39 +66,39 @@
require_once QA_INCLUDE_DIR.'qa-db-users.php'; require_once QA_INCLUDE_DIR.'qa-db-users.php';
$lastuserid=qa_opt('mailing_last_userid'); $lastuserid=qa_opt('mailing_last_userid');
if (strlen($lastuserid)) { if (strlen($lastuserid)) {
$thistime=time(); $thistime=time();
$lasttime=qa_opt('mailing_last_timestamp'); $lasttime=qa_opt('mailing_last_timestamp');
$perminute=qa_opt('mailing_per_minute'); $perminute=qa_opt('mailing_per_minute');
if (($lasttime-$thistime)>60) // if it's been a while, we assume there hasn't been continuous mailing... if (($lasttime-$thistime)>60) // if it's been a while, we assume there hasn't been continuous mailing...
$lasttime=$thistime-1; // ... so only do 1 second's worth $lasttime=$thistime-1; // ... so only do 1 second's worth
else // otherwise... else // otherwise...
$lasttime=max($lasttime, $thistime-6); // ... don't do more than 6 seconds' worth $lasttime=max($lasttime, $thistime-6); // ... don't do more than 6 seconds' worth
$count=min(floor(($thistime-$lasttime)*$perminute/60), 100); // don't do more than 100 messages at a time $count=min(floor(($thistime-$lasttime)*$perminute/60), 100); // don't do more than 100 messages at a time
if ($count>0) { if ($count>0) {
qa_opt('mailing_last_timestamp', $thistime+30); qa_opt('mailing_last_timestamp', $thistime+30);
// prevents a parallel call to qa_mailing_perform_step() from sending messages, unless we're very unlucky with timing (poor man's mutex) // prevents a parallel call to qa_mailing_perform_step() from sending messages, unless we're very unlucky with timing (poor man's mutex)
$sentusers=0; $sentusers=0;
$users=qa_db_users_get_mailing_next($lastuserid, $count); $users=qa_db_users_get_mailing_next($lastuserid, $count);
if (count($users)) { if (count($users)) {
foreach ($users as $user) foreach ($users as $user)
$lastuserid=max($lastuserid, $user['userid']); $lastuserid=max($lastuserid, $user['userid']);
qa_opt('mailing_last_userid', $lastuserid); qa_opt('mailing_last_userid', $lastuserid);
qa_opt('mailing_done_users', qa_opt('mailing_done_users')+count($users)); qa_opt('mailing_done_users', qa_opt('mailing_done_users')+count($users));
foreach ($users as $user) foreach ($users as $user)
if (!($user['flags'] & QA_USER_FLAGS_NO_MAILINGS)) { if (!($user['flags'] & QA_USER_FLAGS_NO_MAILINGS)) {
qa_mailing_send_one($user['userid'], $user['handle'], $user['email'], $user['emailcode']); qa_mailing_send_one($user['userid'], $user['handle'], $user['email'], $user['emailcode']);
$sentusers++; $sentusers++;
} }
qa_opt('mailing_last_timestamp', $lasttime+$sentusers*60/$perminute); // can be floating point result, based on number of mails actually sent qa_opt('mailing_last_timestamp', $lasttime+$sentusers*60/$perminute); // can be floating point result, based on number of mails actually sent
} else } else
...@@ -107,7 +107,7 @@ ...@@ -107,7 +107,7 @@
} }
} }
function qa_mailing_send_one($userid, $handle, $email, $emailcode) function qa_mailing_send_one($userid, $handle, $email, $emailcode)
/* /*
Send a single message from the mailing, to $userid with $handle and $email. Send a single message from the mailing, to $userid with $handle and $email.
...@@ -116,14 +116,14 @@ ...@@ -116,14 +116,14 @@
{ {
require_once QA_INCLUDE_DIR.'qa-app-emails.php'; require_once QA_INCLUDE_DIR.'qa-app-emails.php';
require_once QA_INCLUDE_DIR.'qa-db-users.php'; require_once QA_INCLUDE_DIR.'qa-db-users.php';
if (!strlen(trim($emailcode))) { if (!strlen(trim($emailcode))) {
$emailcode=qa_db_user_rand_emailcode(); $emailcode=qa_db_user_rand_emailcode();
qa_db_user_set($userid, 'emailcode', $emailcode); qa_db_user_set($userid, 'emailcode', $emailcode);
} }
$unsubscribeurl=qa_path_absolute('unsubscribe', array('c' => $emailcode, 'u' => $handle)); $unsubscribeurl=qa_path_absolute('unsubscribe', array('c' => $emailcode, 'u' => $handle));
return qa_send_email(array( return qa_send_email(array(
'fromemail' => qa_opt('mailing_from_email'), 'fromemail' => qa_opt('mailing_from_email'),
'fromname' => qa_opt('mailing_from_name'), 'fromname' => qa_opt('mailing_from_name'),
...@@ -150,7 +150,7 @@ ...@@ -150,7 +150,7 @@
return null; return null;
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
*/ */
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-messages.php File: qa-include/qa-app-messages.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Handling private or public messages (wall posts) Description: Handling private or public messages (wall posts)
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -39,39 +39,39 @@ ...@@ -39,39 +39,39 @@
require_once QA_INCLUDE_DIR.'qa-app-limits.php'; 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_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
if ((!QA_FINAL_EXTERNAL_USERS) && qa_opt('allow_user_walls')) { if ((!QA_FINAL_EXTERNAL_USERS) && qa_opt('allow_user_walls')) {
if ( ($touserflags & QA_USER_FLAGS_NO_WALL_POSTS) && !(isset($fromuserid) && ($fromuserid==$touserid)) ) if ( ($touserflags & QA_USER_FLAGS_NO_WALL_POSTS) && !(isset($fromuserid) && ($fromuserid==$touserid)) )
return qa_lang_html('profile/post_wall_blocked'); return qa_lang_html('profile/post_wall_blocked');
else else
switch (qa_user_permit_error('permit_post_wall', QA_LIMIT_WALL_POSTS)) { switch (qa_user_permit_error('permit_post_wall', QA_LIMIT_WALL_POSTS)) {
case 'limit': case 'limit':
return qa_lang_html('profile/post_wall_limit'); return qa_lang_html('profile/post_wall_limit');
break; break;
case 'login': case 'login':
return qa_insert_login_links(qa_lang_html('profile/post_wall_must_login'), qa_request()); return qa_insert_login_links(qa_lang_html('profile/post_wall_must_login'), qa_request());
break; break;
case 'confirm': case 'confirm':
return qa_insert_login_links(qa_lang_html('profile/post_wall_must_confirm'), qa_request()); return qa_insert_login_links(qa_lang_html('profile/post_wall_must_confirm'), qa_request());
break; break;
case 'approve': case 'approve':
return qa_lang_html('profile/post_wall_must_be_approved'); return qa_lang_html('profile/post_wall_must_be_approved');
break; break;
case false: case false:
return false; return false;
break; break;
} }
} }
return qa_lang_html('users/no_permission'); return qa_lang_html('users/no_permission');
} }
function qa_wall_add_post($userid, $handle, $cookieid, $touserid, $tohandle, $content, $format) function qa_wall_add_post($userid, $handle, $cookieid, $touserid, $tohandle, $content, $format)
/* /*
Adds a post to the wall of user $touserid with handle $tohandle, containing $content in $format (e.g. '' for text or 'html') Adds a post to the wall of user $touserid with handle $tohandle, containing $content in $format (e.g. '' for text or 'html')
...@@ -79,13 +79,13 @@ ...@@ -79,13 +79,13 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } 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-app-format.php';
require_once QA_INCLUDE_DIR.'qa-db-messages.php'; require_once QA_INCLUDE_DIR.'qa-db-messages.php';
$messageid=qa_db_message_create($userid, $touserid, $content, $format, true); $messageid=qa_db_message_create($userid, $touserid, $content, $format, true);
qa_db_user_recount_posts($touserid); qa_db_user_recount_posts($touserid);
qa_report_event('u_wall_post', $userid, $handle, $cookieid, array( qa_report_event('u_wall_post', $userid, $handle, $cookieid, array(
'userid' => $touserid, 'userid' => $touserid,
'handle' => $tohandle, 'handle' => $tohandle,
...@@ -97,8 +97,8 @@ ...@@ -97,8 +97,8 @@
return $messageid; return $messageid;
} }
function qa_wall_delete_post($userid, $handle, $cookieid, $message) function qa_wall_delete_post($userid, $handle, $cookieid, $message)
/* /*
Deletes the wall post described in $message (as obtained via qa_db_recent_messages_selectspec()). The deletion was performed Deletes the wall post described in $message (as obtained via qa_db_recent_messages_selectspec()). The deletion was performed
...@@ -106,17 +106,17 @@ ...@@ -106,17 +106,17 @@
*/ */
{ {
require_once QA_INCLUDE_DIR.'qa-db-messages.php'; require_once QA_INCLUDE_DIR.'qa-db-messages.php';
qa_db_message_delete($message['messageid']); qa_db_message_delete($message['messageid']);
qa_db_user_recount_posts($message['touserid']); qa_db_user_recount_posts($message['touserid']);
qa_report_event('u_wall_delete', $userid, $handle, $cookieid, array( qa_report_event('u_wall_delete', $userid, $handle, $cookieid, array(
'messageid' => $message['messageid'], 'messageid' => $message['messageid'],
'oldmessage' => $message, 'oldmessage' => $message,
)); ));
} }
function qa_wall_posts_add_rules($usermessages, $start) function qa_wall_posts_add_rules($usermessages, $start)
/* /*
Return the list of messages in $usermessages (as obtained via qa_db_recent_messages_selectspec()) with additional Return the list of messages in $usermessages (as obtained via qa_db_recent_messages_selectspec()) with additional
...@@ -125,26 +125,26 @@ ...@@ -125,26 +125,26 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$userid=qa_get_logged_in_userid(); $userid=qa_get_logged_in_userid();
$userdeleteall=!(qa_user_permit_error('permit_hide_show') || qa_user_permit_error('permit_delete_hidden')); $userdeleteall=!(qa_user_permit_error('permit_hide_show') || qa_user_permit_error('permit_delete_hidden'));
// reuse "Hiding or showing any post" and "Deleting hidden posts" permissions // reuse "Hiding or showing any post" and "Deleting hidden posts" permissions
$userrecent=($start==0) && isset($userid); // User can delete all of the recent messages they wrote on someone's wall... $userrecent=($start==0) && isset($userid); // User can delete all of the recent messages they wrote on someone's wall...
foreach ($usermessages as $key => $message) { foreach ($usermessages as $key => $message) {
if ($message['fromuserid']!=$userid) if ($message['fromuserid']!=$userid)
$userrecent=false; // ... until we come across one that they didn't write (which could be a reply) $userrecent=false; // ... until we come across one that they didn't write (which could be a reply)
$usermessages[$key]['deleteable'] = $usermessages[$key]['deleteable'] =
($message['touserid']==$userid) || // if it's this user's wall ($message['touserid']==$userid) || // if it's this user's wall
($userrecent && ($message['fromuserid']==$userid)) || // if it's one the user wrote that no one replied to yet ($userrecent && ($message['fromuserid']==$userid)) || // if it's one the user wrote that no one replied to yet
$userdeleteall; // if the user has enough permissions to delete from any wall $userdeleteall; // if the user has enough permissions to delete from any wall
} }
return $usermessages; return $usermessages;
} }
function qa_wall_post_view($message) function qa_wall_post_view($message)
/* /*
Returns an element to add to $qa_content['message_list']['messages'] for $message (as obtained via Returns an element to add to $qa_content['message_list']['messages'] for $message (as obtained via
...@@ -152,11 +152,11 @@ ...@@ -152,11 +152,11 @@
*/ */
{ {
require_once QA_INCLUDE_DIR.'qa-app-format.php'; require_once QA_INCLUDE_DIR.'qa-app-format.php';
$options=qa_message_html_defaults(); $options=qa_message_html_defaults();
$htmlfields=qa_message_html_fields($message, $options); $htmlfields=qa_message_html_fields($message, $options);
if ($message['deleteable']) if ($message['deleteable'])
$htmlfields['form']=array( $htmlfields['form']=array(
'style' => 'light', 'style' => 'light',
...@@ -169,11 +169,11 @@ ...@@ -169,11 +169,11 @@
), ),
), ),
); );
return $htmlfields; return $htmlfields;
} }
function qa_wall_view_more_link($handle, $start) function qa_wall_view_more_link($handle, $start)
/* /*
Returns an element to add to $qa_content['message_list']['messages'] with a link to view all wall posts Returns an element to add to $qa_content['message_list']['messages'] with a link to view all wall posts
......
<?php <?php
/* /*
Question2Answer (c) Gideon Greenspan Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-post-create.php File: qa-include/qa-app-post-create.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Creating questions, answers and comments (application level) Description: Creating questions, answers and comments (application level)
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
require_once QA_INCLUDE_DIR.'qa-db-points.php'; require_once QA_INCLUDE_DIR.'qa-db-points.php';
require_once QA_INCLUDE_DIR.'qa-db-hotness.php'; require_once QA_INCLUDE_DIR.'qa-db-hotness.php';
require_once QA_INCLUDE_DIR.'qa-util-string.php'; require_once QA_INCLUDE_DIR.'qa-util-string.php';
function qa_combine_notify_email($userid, $notify, $email) function qa_combine_notify_email($userid, $notify, $email)
/* /*
Return value to store in database combining $notify and $email values entered by user $userid (or null for anonymous) Return value to store in database combining $notify and $email values entered by user $userid (or null for anonymous)
...@@ -43,8 +43,8 @@ ...@@ -43,8 +43,8 @@
{ {
return $notify ? (empty($email) ? (isset($userid) ? '@' : null) : $email) : null; return $notify ? (empty($email) ? (isset($userid) ? '@' : null) : $email) : null;
} }
function qa_question_create($followanswer, $userid, $handle, $cookieid, $title, $content, $format, $text, $tagstring, $notify, $email, function qa_question_create($followanswer, $userid, $handle, $cookieid, $title, $content, $format, $text, $tagstring, $notify, $email,
$categoryid=null, $extravalue=null, $queued=false, $name=null) $categoryid=null, $extravalue=null, $queued=false, $name=null)
/* /*
...@@ -58,15 +58,15 @@ ...@@ -58,15 +58,15 @@
$postid=qa_db_post_create($queued ? 'Q_QUEUED' : 'Q', @$followanswer['postid'], $userid, isset($userid) ? null : $cookieid, $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), qa_remote_ip_address(), $title, $content, $format, $tagstring, qa_combine_notify_email($userid, $notify, $email),
$categoryid, isset($userid) ? null : $name); $categoryid, isset($userid) ? null : $name);
if (isset($extravalue)) { if (isset($extravalue)) {
require_once QA_INCLUDE_DIR.'qa-db-metas.php'; require_once QA_INCLUDE_DIR.'qa-db-metas.php';
qa_db_postmeta_set($postid, 'qa_q_extra', $extravalue); qa_db_postmeta_set($postid, 'qa_q_extra', $extravalue);
} }
qa_db_posts_calc_category_path($postid); qa_db_posts_calc_category_path($postid);
qa_db_hotness_update($postid); qa_db_hotness_update($postid);
if ($queued) { if ($queued) {
qa_db_queuedcount_update(); qa_db_queuedcount_update();
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
qa_update_counts_for_q($postid); qa_update_counts_for_q($postid);
qa_db_points_update_ifuser($userid, 'qposts'); qa_db_points_update_ifuser($userid, 'qposts');
} }
qa_report_event($queued ? 'q_queue' : 'q_post', $userid, $handle, $cookieid, array( qa_report_event($queued ? 'q_queue' : 'q_post', $userid, $handle, $cookieid, array(
'postid' => $postid, 'postid' => $postid,
'parentid' => @$followanswer['postid'], 'parentid' => @$followanswer['postid'],
...@@ -91,11 +91,11 @@ ...@@ -91,11 +91,11 @@
'notify' => $notify, 'notify' => $notify,
'email' => $email, 'email' => $email,
)); ));
return $postid; return $postid;
} }
function qa_update_counts_for_q($postid) function qa_update_counts_for_q($postid)
/* /*
Perform various common cached count updating operations to reflect changes in the question whose id is $postid Perform various common cached count updating operations to reflect changes in the question whose id is $postid
...@@ -103,14 +103,14 @@ ...@@ -103,14 +103,14 @@
{ {
if (isset($postid)) // post might no longer exist if (isset($postid)) // post might no longer exist
qa_db_category_path_qcount_update(qa_db_post_get_category_path($postid)); qa_db_category_path_qcount_update(qa_db_post_get_category_path($postid));
qa_db_qcount_update(); qa_db_qcount_update();
qa_db_unaqcount_update(); qa_db_unaqcount_update();
qa_db_unselqcount_update(); qa_db_unselqcount_update();
qa_db_unupaqcount_update(); qa_db_unupaqcount_update();
} }
function qa_array_filter_by_keys($inarray, $keys) function qa_array_filter_by_keys($inarray, $keys)
/* /*
Return an array containing the elements of $inarray whose key is in $keys Return an array containing the elements of $inarray whose key is in $keys
...@@ -121,11 +121,11 @@ ...@@ -121,11 +121,11 @@
foreach ($keys as $key) foreach ($keys as $key)
if (isset($inarray[$key])) if (isset($inarray[$key]))
$outarray[$key]=$inarray[$key]; $outarray[$key]=$inarray[$key];
return $outarray; return $outarray;
} }
function qa_suspend_post_indexing($suspend=true) function qa_suspend_post_indexing($suspend=true)
/* /*
Suspend the indexing (and unindexing) of posts via qa_post_index(...) and qa_post_unindex(...) Suspend the indexing (and unindexing) of posts via qa_post_index(...) and qa_post_unindex(...)
...@@ -133,11 +133,11 @@ ...@@ -133,11 +133,11 @@
*/ */
{ {
global $qa_post_indexing_suspended; global $qa_post_indexing_suspended;
$qa_post_indexing_suspended+=($suspend ? 1 : -1); $qa_post_indexing_suspended+=($suspend ? 1 : -1);
} }
function qa_post_index($postid, $type, $questionid, $parentid, $title, $content, $format, $text, $tagstring, $categoryid) function qa_post_index($postid, $type, $questionid, $parentid, $title, $content, $format, $text, $tagstring, $categoryid)
/* /*
Add post $postid (which comes under $questionid) of $type (Q/A/C) to the database index, with $title, $text, Add post $postid (which comes under $questionid) of $type (Q/A/C) to the database index, with $title, $text,
...@@ -145,18 +145,18 @@ ...@@ -145,18 +145,18 @@
*/ */
{ {
global $qa_post_indexing_suspended; global $qa_post_indexing_suspended;
if ($qa_post_indexing_suspended>0) if ($qa_post_indexing_suspended>0)
return; return;
// Send through to any search modules for indexing // Send through to any search modules for indexing
$searches=qa_load_modules_with('search', 'index_post'); $searches=qa_load_modules_with('search', 'index_post');
foreach ($searches as $search) foreach ($searches as $search)
$search->index_post($postid, $type, $questionid, $parentid, $title, $content, $format, $text, $tagstring, $categoryid); $search->index_post($postid, $type, $questionid, $parentid, $title, $content, $format, $text, $tagstring, $categoryid);
} }
function qa_answer_create($userid, $handle, $cookieid, $content, $format, $text, $notify, $email, $question, $queued=false, $name=null) 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. Add an answer (application level) - create record, update appropriate counts, index it, send notifications.
...@@ -167,20 +167,20 @@ ...@@ -167,20 +167,20 @@
$postid=qa_db_post_create($queued ? 'A_QUEUED' : 'A', $question['postid'], $userid, isset($userid) ? null : $cookieid, $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), qa_remote_ip_address(), null, $content, $format, null, qa_combine_notify_email($userid, $notify, $email),
$question['categoryid'], isset($userid) ? null : $name); $question['categoryid'], isset($userid) ? null : $name);
qa_db_posts_calc_category_path($postid); qa_db_posts_calc_category_path($postid);
if ($queued) { if ($queued) {
qa_db_queuedcount_update(); qa_db_queuedcount_update();
} else { } else {
if ($question['type']=='Q') // don't index answer if parent question is hidden or queued 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_post_index($postid, 'A', $question['postid'], $question['postid'], null, $content, $format, $text, null, $question['categoryid']);
qa_update_q_counts_for_a($question['postid']); qa_update_q_counts_for_a($question['postid']);
qa_db_points_update_ifuser($userid, 'aposts'); qa_db_points_update_ifuser($userid, 'aposts');
} }
qa_report_event($queued ? 'a_queue' : 'a_post', $userid, $handle, $cookieid, array( qa_report_event($queued ? 'a_queue' : 'a_post', $userid, $handle, $cookieid, array(
'postid' => $postid, 'postid' => $postid,
'parentid' => $question['postid'], 'parentid' => $question['postid'],
...@@ -193,11 +193,11 @@ ...@@ -193,11 +193,11 @@
'notify' => $notify, 'notify' => $notify,
'email' => $email, 'email' => $email,
)); ));
return $postid; return $postid;
} }
function qa_update_q_counts_for_a($questionid) function qa_update_q_counts_for_a($questionid)
/* /*
Perform various common cached count updating operations to reflect changes in an answer of question $questionid Perform various common cached count updating operations to reflect changes in an answer of question $questionid
...@@ -210,7 +210,7 @@ ...@@ -210,7 +210,7 @@
qa_db_unupaqcount_update(); qa_db_unupaqcount_update();
} }
function qa_comment_create($userid, $handle, $cookieid, $content, $format, $text, $notify, $email, $question, $parent, $commentsfollows, $queued=false, $name=null) 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. Add a comment (application level) - create record, update appropriate counts, index it, send notifications.
...@@ -228,26 +228,26 @@ ...@@ -228,26 +228,26 @@
if (!isset($parent)) if (!isset($parent))
$parent=$question; // for backwards compatibility with old answer parameter $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, $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), qa_remote_ip_address(), null, $content, $format, null, qa_combine_notify_email($userid, $notify, $email),
$question['categoryid'], isset($userid) ? null : $name); $question['categoryid'], isset($userid) ? null : $name);
qa_db_posts_calc_category_path($postid); qa_db_posts_calc_category_path($postid);
if ($queued) { if ($queued) {
qa_db_queuedcount_update(); qa_db_queuedcount_update();
} else { } else {
if ( ($question['type']=='Q') && (($parent['type']=='Q') || ($parent['type']=='A')) ) // only index if antecedents fully visible 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']); qa_post_index($postid, 'C', $question['postid'], $parent['postid'], null, $content, $format, $text, null, $question['categoryid']);
qa_db_points_update_ifuser($userid, 'cposts'); qa_db_points_update_ifuser($userid, 'cposts');
qa_db_ccount_update(); qa_db_ccount_update();
} }
$thread=array(); $thread=array();
foreach ($commentsfollows as $comment) foreach ($commentsfollows as $comment)
if (($comment['type']=='C') && ($comment['parentid']==$parent['postid'])) // find just those for this parent, fully visible if (($comment['type']=='C') && ($comment['parentid']==$parent['postid'])) // find just those for this parent, fully visible
$thread[]=$comment; $thread[]=$comment;
...@@ -268,10 +268,10 @@ ...@@ -268,10 +268,10 @@
'notify' => $notify, 'notify' => $notify,
'email' => $email, 'email' => $email,
)); ));
return $postid; return $postid;
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-q-list.php File: qa-include/qa-app-q-list.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Controller for most question listing pages, plus custom pages and plugin pages Description: Controller for most question listing pages, plus custom pages and plugin pages
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
exit; exit;
} }
function qa_q_list_page_content($questions, $pagesize, $start, $count, $sometitle, $nonetitle, function qa_q_list_page_content($questions, $pagesize, $start, $count, $sometitle, $nonetitle,
$navcategories, $categoryid, $categoryqcount, $categorypathprefix, $feedpathprefix, $suggest, $navcategories, $categoryid, $categoryqcount, $categorypathprefix, $feedpathprefix, $suggest,
$pagelinkparams=null, $categoryparams=null, $dummy=null) $pagelinkparams=null, $categoryparams=null, $dummy=null)
...@@ -48,76 +48,76 @@ ...@@ -48,76 +48,76 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } 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-app-format.php';
require_once QA_INCLUDE_DIR.'qa-app-updates.php'; require_once QA_INCLUDE_DIR.'qa-app-updates.php';
$userid=qa_get_logged_in_userid(); $userid=qa_get_logged_in_userid();
// Chop down to size, get user information for display // Chop down to size, get user information for display
if (isset($pagesize)) if (isset($pagesize))
$questions=array_slice($questions, 0, $pagesize); $questions=array_slice($questions, 0, $pagesize);
$usershtml=qa_userids_handles_html(qa_any_get_userids_handles($questions)); $usershtml=qa_userids_handles_html(qa_any_get_userids_handles($questions));
// Prepare content for theme // Prepare content for theme
$qa_content=qa_content_prepare(true, array_keys(qa_category_path($navcategories, $categoryid))); $qa_content=qa_content_prepare(true, array_keys(qa_category_path($navcategories, $categoryid)));
$qa_content['q_list']['form']=array( $qa_content['q_list']['form']=array(
'tags' => 'method="post" action="'.qa_self_html().'"', 'tags' => 'method="post" action="'.qa_self_html().'"',
'hidden' => array( 'hidden' => array(
'code' => qa_get_form_security_code('vote'), 'code' => qa_get_form_security_code('vote'),
), ),
); );
$qa_content['q_list']['qs']=array(); $qa_content['q_list']['qs']=array();
if (count($questions)) { if (count($questions)) {
$qa_content['title']=$sometitle; $qa_content['title']=$sometitle;
$defaults=qa_post_html_defaults('Q'); $defaults=qa_post_html_defaults('Q');
if (isset($categorypathprefix)) if (isset($categorypathprefix))
$defaults['categorypathprefix']=$categorypathprefix; $defaults['categorypathprefix']=$categorypathprefix;
foreach ($questions as $question) foreach ($questions as $question)
$qa_content['q_list']['qs'][]=qa_any_to_q_html_fields($question, $userid, qa_cookie_get(), $qa_content['q_list']['qs'][]=qa_any_to_q_html_fields($question, $userid, qa_cookie_get(),
$usershtml, null, qa_post_html_options($question, $defaults)); $usershtml, null, qa_post_html_options($question, $defaults));
} else } else
$qa_content['title']=$nonetitle; $qa_content['title']=$nonetitle;
if (isset($userid) && isset($categoryid)) { if (isset($userid) && isset($categoryid)) {
$favoritemap=qa_get_favorite_non_qs_map(); $favoritemap=qa_get_favorite_non_qs_map();
$categoryisfavorite=@$favoritemap['category'][$navcategories[$categoryid]['backpath']] ? true : false; $categoryisfavorite=@$favoritemap['category'][$navcategories[$categoryid]['backpath']] ? true : false;
$qa_content['favorite']=qa_favorite_form(QA_ENTITY_CATEGORY, $categoryid, $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'])); qa_lang_sub($categoryisfavorite ? 'main/remove_x_favorites' : 'main/add_category_x_favorites', $navcategories[$categoryid]['title']));
} }
if (isset($count) && isset($pagesize)) if (isset($count) && isset($pagesize))
$qa_content['page_links']=qa_html_page_links(qa_request(), $start, $pagesize, $count, qa_opt('pages_prev_next'), $pagelinkparams); $qa_content['page_links']=qa_html_page_links(qa_request(), $start, $pagesize, $count, qa_opt('pages_prev_next'), $pagelinkparams);
if (empty($qa_content['page_links'])) if (empty($qa_content['page_links']))
$qa_content['suggest_next']=$suggest; $qa_content['suggest_next']=$suggest;
if (qa_using_categories() && count($navcategories) && isset($categorypathprefix)) if (qa_using_categories() && count($navcategories) && isset($categorypathprefix))
$qa_content['navigation']['cat']=qa_category_navigation($navcategories, $categoryid, $categorypathprefix, $categoryqcount, $categoryparams); $qa_content['navigation']['cat']=qa_category_navigation($navcategories, $categoryid, $categorypathprefix, $categoryqcount, $categoryparams);
if (isset($feedpathprefix) && (qa_opt('feed_per_category') || !isset($categoryid)) ) if (isset($feedpathprefix) && (qa_opt('feed_per_category') || !isset($categoryid)) )
$qa_content['feed']=array( $qa_content['feed']=array(
'url' => qa_path_html(qa_feed_request($feedpathprefix.(isset($categoryid) ? ('/'.qa_category_path_request($navcategories, $categoryid)) : ''))), 'url' => qa_path_html(qa_feed_request($feedpathprefix.(isset($categoryid) ? ('/'.qa_category_path_request($navcategories, $categoryid)) : ''))),
'label' => strip_tags($sometitle), 'label' => strip_tags($sometitle),
); );
return $qa_content; return $qa_content;
} }
function qa_qs_sub_navigation($sort, $categoryslugs) function qa_qs_sub_navigation($sort, $categoryslugs)
/* /*
Return the sub navigation structure common to question listing pages Return the sub navigation structure common to question listing pages
...@@ -134,12 +134,12 @@ ...@@ -134,12 +134,12 @@
'label' => qa_lang('main/nav_most_recent'), 'label' => qa_lang('main/nav_most_recent'),
'url' => qa_path_html($request), 'url' => qa_path_html($request),
), ),
'hot' => array( 'hot' => array(
'label' => qa_lang('main/nav_hot'), 'label' => qa_lang('main/nav_hot'),
'url' => qa_path_html($request, array('sort' => 'hot')), 'url' => qa_path_html($request, array('sort' => 'hot')),
), ),
'votes' => array( 'votes' => array(
'label' => qa_lang('main/nav_most_votes'), 'label' => qa_lang('main/nav_most_votes'),
'url' => qa_path_html($request, array('sort' => 'votes')), 'url' => qa_path_html($request, array('sort' => 'votes')),
...@@ -155,19 +155,19 @@ ...@@ -155,19 +155,19 @@
'url' => qa_path_html($request, array('sort' => 'views')), 'url' => qa_path_html($request, array('sort' => 'views')),
), ),
); );
if (isset($navigation[$sort])) if (isset($navigation[$sort]))
$navigation[$sort]['selected']=true; $navigation[$sort]['selected']=true;
else else
$navigation['recent']['selected']=true; $navigation['recent']['selected']=true;
if (!qa_opt('do_count_q_views')) if (!qa_opt('do_count_q_views'))
unset($navigation['views']); unset($navigation['views']);
return $navigation; return $navigation;
} }
function qa_unanswered_sub_navigation($by, $categoryslugs) function qa_unanswered_sub_navigation($by, $categoryslugs)
/* /*
Return the sub navigation structure common to unanswered pages Return the sub navigation structure common to unanswered pages
...@@ -178,29 +178,29 @@ ...@@ -178,29 +178,29 @@
if (isset($categoryslugs)) if (isset($categoryslugs))
foreach ($categoryslugs as $slug) foreach ($categoryslugs as $slug)
$request.='/'.$slug; $request.='/'.$slug;
$navigation=array( $navigation=array(
'by-answers' => array( 'by-answers' => array(
'label' => qa_lang('main/nav_no_answer'), 'label' => qa_lang('main/nav_no_answer'),
'url' => qa_path_html($request), 'url' => qa_path_html($request),
), ),
'by-selected' => array( 'by-selected' => array(
'label' => qa_lang('main/nav_no_selected_answer'), 'label' => qa_lang('main/nav_no_selected_answer'),
'url' => qa_path_html($request, array('by' => 'selected')), 'url' => qa_path_html($request, array('by' => 'selected')),
), ),
'by-upvotes' => array( 'by-upvotes' => array(
'label' => qa_lang('main/nav_no_upvoted_answer'), 'label' => qa_lang('main/nav_no_upvoted_answer'),
'url' => qa_path_html($request, array('by' => 'upvotes')), 'url' => qa_path_html($request, array('by' => 'upvotes')),
), ),
); );
if (isset($navigation['by-'.$by])) if (isset($navigation['by-'.$by]))
$navigation['by-'.$by]['selected']=true; $navigation['by-'.$by]['selected']=true;
else else
$navigation['by-answers']['selected']=true; $navigation['by-answers']['selected']=true;
if (!qa_opt('voting_on_as')) if (!qa_opt('voting_on_as'))
unset($navigation['by-upvotes']); unset($navigation['by-upvotes']);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-search.php File: qa-include/qa-app-search.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Wrapper functions and utilities for search modules Description: Wrapper functions and utilities for search modules
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
exit; exit;
} }
function qa_get_search_results($query, $start, $count, $userid, $absoluteurls, $fullcontent) function qa_get_search_results($query, $start, $count, $userid, $absoluteurls, $fullcontent)
/* /*
Returns $count search results for $query performed by $userid, starting at offset $start. Set $absoluteurls to true Returns $count search results for $query performed by $userid, starting at offset $start. Set $absoluteurls to true
...@@ -40,36 +40,36 @@ ...@@ -40,36 +40,36 @@
{ {
// Identify which search module should be used // Identify which search module should be used
$searchmodules=qa_load_modules_with('search', 'process_search'); $searchmodules=qa_load_modules_with('search', 'process_search');
if (!count($searchmodules)) if (!count($searchmodules))
qa_fatal_error('No search engine is available'); qa_fatal_error('No search engine is available');
$module=reset($searchmodules); // use first one by default $module=reset($searchmodules); // use first one by default
if (count($searchmodules)>1) { if (count($searchmodules)>1) {
$tryname=qa_opt('search_module'); // use chosen one if it's available $tryname=qa_opt('search_module'); // use chosen one if it's available
if (isset($searchmodules[$tryname])) if (isset($searchmodules[$tryname]))
$module=$searchmodules[$tryname]; $module=$searchmodules[$tryname];
} }
// Get the results // Get the results
$results=$module->process_search($query, $start, $count, $userid, $absoluteurls, $fullcontent); $results=$module->process_search($query, $start, $count, $userid, $absoluteurls, $fullcontent);
// Work out what additional information (if any) we need to retrieve for the results // Work out what additional information (if any) we need to retrieve for the results
$keypostidgetfull=array(); $keypostidgetfull=array();
$keypostidgettype=array(); $keypostidgettype=array();
$keypostidgetquestion=array(); $keypostidgetquestion=array();
$keypageidgetpage=array(); $keypageidgetpage=array();
foreach ($results as $result) { foreach ($results as $result) {
if (isset($result['question_postid']) && !isset($result['question'])) if (isset($result['question_postid']) && !isset($result['question']))
$keypostidgetfull[$result['question_postid']]=true; $keypostidgetfull[$result['question_postid']]=true;
if (isset($result['match_postid'])) { if (isset($result['match_postid'])) {
if (!( (isset($result['question_postid'])) || (isset($result['question'])) )) if (!( (isset($result['question_postid'])) || (isset($result['question'])) ))
$keypostidgetquestion[$result['match_postid']]=true; // we can also get $result['match_type'] from this $keypostidgetquestion[$result['match_postid']]=true; // we can also get $result['match_type'] from this
...@@ -77,22 +77,22 @@ ...@@ -77,22 +77,22 @@
elseif (!isset($result['match_type'])) elseif (!isset($result['match_type']))
$keypostidgettype[$result['match_postid']]=true; $keypostidgettype[$result['match_postid']]=true;
} }
if (isset($result['page_pageid']) && !isset($result['page'])) if (isset($result['page_pageid']) && !isset($result['page']))
$keypageidgetpage[$result['page_pageid']]=true; $keypageidgetpage[$result['page_pageid']]=true;
} }
// Perform the appropriate database queries // 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($keypostidgetfull) ? qa_db_posts_selectspec($userid, array_keys($keypostidgetfull), $fullcontent) : null,
count($keypostidgettype) ? qa_db_posts_basetype_selectspec(array_keys($keypostidgettype)) : null, count($keypostidgettype) ? qa_db_posts_basetype_selectspec(array_keys($keypostidgettype)) : null,
count($keypostidgetquestion) ? qa_db_posts_to_qs_selectspec($userid, array_keys($keypostidgetquestion), $fullcontent) : null, count($keypostidgetquestion) ? qa_db_posts_to_qs_selectspec($userid, array_keys($keypostidgetquestion), $fullcontent) : null,
count($keypageidgetpage) ? qa_db_pages_selectspec(null, array_keys($keypageidgetpage)) : null count($keypageidgetpage) ? qa_db_pages_selectspec(null, array_keys($keypageidgetpage)) : null
); );
// Supplement the results as appropriate // Supplement the results as appropriate
foreach ($results as $key => $result) { foreach ($results as $key => $result) {
if (isset($result['question_postid']) && !isset($result['question'])) if (isset($result['question_postid']) && !isset($result['question']))
if (@$postidfull[$result['question_postid']]['basetype']=='Q') if (@$postidfull[$result['question_postid']]['basetype']=='Q')
...@@ -101,27 +101,27 @@ ...@@ -101,27 +101,27 @@
if (isset($result['match_postid'])) { if (isset($result['match_postid'])) {
if (!( (isset($result['question_postid'])) || (isset($result['question'])) )) { if (!( (isset($result['question_postid'])) || (isset($result['question'])) )) {
$result['question']=@$postidquestion[$result['match_postid']]; $result['question']=@$postidquestion[$result['match_postid']];
if (!isset($result['match_type'])) if (!isset($result['match_type']))
$result['match_type']=@$result['question']['obasetype']; $result['match_type']=@$result['question']['obasetype'];
} elseif (!isset($result['match_type'])) } elseif (!isset($result['match_type']))
$result['match_type']=@$postidtype[$result['match_postid']]; $result['match_type']=@$postidtype[$result['match_postid']];
} }
if (isset($result['question']) && !isset($result['question_postid'])) if (isset($result['question']) && !isset($result['question_postid']))
$result['question_postid']=$result['question']['postid']; $result['question_postid']=$result['question']['postid'];
if (isset($result['page_pageid']) && !isset($result['page'])) if (isset($result['page_pageid']) && !isset($result['page']))
$result['page']=@$pageidpage[$result['page_pageid']]; $result['page']=@$pageidpage[$result['page_pageid']];
if (!isset($result['title'])) { if (!isset($result['title'])) {
if (isset($result['question'])) if (isset($result['question']))
$result['title']=$result['question']['title']; $result['title']=$result['question']['title'];
elseif (isset($result['page'])) elseif (isset($result['page']))
$result['title']=$result['page']['heading']; $result['title']=$result['page']['heading'];
} }
if (!isset($result['url'])) { if (!isset($result['url'])) {
if (isset($result['question'])) if (isset($result['question']))
$result['url']=qa_q_path($result['question']['postid'], $result['question']['title'], $result['url']=qa_q_path($result['question']['postid'], $result['question']['title'],
...@@ -129,15 +129,15 @@ ...@@ -129,15 +129,15 @@
elseif (isset($result['page'])) elseif (isset($result['page']))
$result['url']=qa_path($result['page']['tags'], null, qa_opt('site_url')); $result['url']=qa_path($result['page']['tags'], null, qa_opt('site_url'));
} }
$results[$key]=$result; $results[$key]=$result;
} }
// Return the results // Return the results
return $results; return $results;
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-updates.php File: qa-include/qa-app-updates.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Definitions relating to favorites and updates in the database tables Description: Definitions relating to favorites and updates in the database tables
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
define('QA_ENTITY_TAG', 'T'); define('QA_ENTITY_TAG', 'T');
define('QA_ENTITY_CATEGORY', 'C'); define('QA_ENTITY_CATEGORY', 'C');
define('QA_ENTITY_NONE', '-'); define('QA_ENTITY_NONE', '-');
// Character codes for the different types of updates on a post (updatetype columns) // Character codes for the different types of updates on a post (updatetype columns)
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
// Character codes for types of update that only appear in the streams tables, not on the posts themselves // 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_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_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 define('QA_UPDATE_C_FOR_A', 'N'); // if comment created was on an answer of the user whose stream this appears in
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-upload.php File: qa-include/qa-app-upload.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Application-level file upload functionality Description: Application-level file upload functionality
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -29,18 +29,18 @@ ...@@ -29,18 +29,18 @@
exit; exit;
} }
function qa_get_max_upload_size() function qa_get_max_upload_size()
/* /*
Return the maximum size of file that can be uploaded, based on database and PHP limits 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); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$mindb=16777215; // from MEDIUMBLOB column type $mindb=16777215; // from MEDIUMBLOB column type
$minphp=trim(ini_get('upload_max_filesize')); $minphp=trim(ini_get('upload_max_filesize'));
switch (strtolower(substr($minphp, -1))) { switch (strtolower(substr($minphp, -1))) {
case 'g': case 'g':
$minphp*=1024; $minphp*=1024;
...@@ -49,11 +49,11 @@ ...@@ -49,11 +49,11 @@
case 'k': case 'k':
$minphp*=1024; $minphp*=1024;
} }
return min($mindb, $minphp); return min($mindb, $minphp);
} }
function qa_upload_file($localfilename, $sourcefilename, $maxfilesize=null, $onlyimage=false, $imagemaxwidth=null, $imagemaxheight=null) function qa_upload_file($localfilename, $sourcefilename, $maxfilesize=null, $onlyimage=false, $imagemaxwidth=null, $imagemaxheight=null)
/* /*
Move an uploaded image or other file into blob storage. Pass the $localfilename where the file is currently stored Move an uploaded image or other file into blob storage. Pass the $localfilename where the file is currently stored
...@@ -72,20 +72,20 @@ ...@@ -72,20 +72,20 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$result=array(); $result=array();
// Check per-user upload limits // Check per-user upload limits
require_once QA_INCLUDE_DIR.'qa-app-users.php'; require_once QA_INCLUDE_DIR.'qa-app-users.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php'; require_once QA_INCLUDE_DIR.'qa-app-limits.php';
switch (qa_user_permit_error(null, QA_LIMIT_UPLOADS)) switch (qa_user_permit_error(null, QA_LIMIT_UPLOADS))
{ {
case 'limit': case 'limit':
$result['error']=qa_lang('main/upload_limit'); $result['error']=qa_lang('main/upload_limit');
return $result; return $result;
case false: case false:
qa_limits_increment(qa_get_logged_in_userid(), QA_LIMIT_UPLOADS); qa_limits_increment(qa_get_logged_in_userid(), QA_LIMIT_UPLOADS);
break; break;
...@@ -94,72 +94,72 @@ ...@@ -94,72 +94,72 @@
$result['error']=qa_lang('users/no_permission'); $result['error']=qa_lang('users/no_permission');
return $result; return $result;
} }
// Check the uploaded file is not too large // Check the uploaded file is not too large
$filesize=filesize($localfilename); $filesize=filesize($localfilename);
if (isset($maxfilesize)) if (isset($maxfilesize))
$maxfilesize=min($maxfilesize, qa_get_max_upload_size()); $maxfilesize=min($maxfilesize, qa_get_max_upload_size());
else else
$maxfilesize=qa_get_max_upload_size(); $maxfilesize=qa_get_max_upload_size();
if ( ($filesize<=0) || ($filesize>$maxfilesize) ) { // if file was too big for PHP, $filesize will be zero 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'); $result['error']=qa_lang_sub('main/max_upload_size_x', number_format($maxfilesize/1048576, 1).'MB');
return $result; return $result;
} }
// Find out what type of source file was uploaded and if appropriate, check it's an image and get preliminary size measure // 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); $pathinfo=pathinfo($sourcefilename);
$format=strtolower(@$pathinfo['extension']); $format=strtolower(@$pathinfo['extension']);
$isimage=($format=='png') || ($format=='gif') || ($format=='jpeg') || ($format=='jpg'); // allowed image extensions $isimage=($format=='png') || ($format=='gif') || ($format=='jpeg') || ($format=='jpg'); // allowed image extensions
if ($isimage) { if ($isimage) {
$imagesize=@getimagesize($localfilename); $imagesize=@getimagesize($localfilename);
if (is_array($imagesize)) { if (is_array($imagesize)) {
$result['width']=$imagesize[0]; $result['width']=$imagesize[0];
$result['height']=$imagesize[1]; $result['height']=$imagesize[1];
switch ($imagesize['2']) { // reassign format based on actual content, if we can switch ($imagesize['2']) { // reassign format based on actual content, if we can
case IMAGETYPE_GIF: case IMAGETYPE_GIF:
$format='gif'; $format='gif';
break; break;
case IMAGETYPE_JPEG: case IMAGETYPE_JPEG:
$format='jpeg'; $format='jpeg';
break; break;
case IMAGETYPE_PNG: case IMAGETYPE_PNG:
$format='png'; $format='png';
break; break;
} }
} }
} }
$result['format']=$format; $result['format']=$format;
if ($onlyimage) if ($onlyimage)
if ( (!$isimage) || !is_array($imagesize) ) { if ( (!$isimage) || !is_array($imagesize) ) {
$result['error']=qa_lang_sub('main/image_not_read', 'GIF, JPG, PNG'); $result['error']=qa_lang_sub('main/image_not_read', 'GIF, JPG, PNG');
return $result; return $result;
} }
// Read in the raw file contents // Read in the raw file contents
$content=file_get_contents($localfilename); $content=file_get_contents($localfilename);
// If appropriate, get more accurate image size and apply constraints to it // If appropriate, get more accurate image size and apply constraints to it
require_once QA_INCLUDE_DIR.'qa-util-image.php'; require_once QA_INCLUDE_DIR.'qa-util-image.php';
if ($isimage && qa_has_gd_image()) { if ($isimage && qa_has_gd_image()) {
$image=@imagecreatefromstring($content); $image=@imagecreatefromstring($content);
if (is_resource($image)) { if (is_resource($image)) {
$result['width']=$width=imagesx($image); $result['width']=$width=imagesx($image);
$result['height']=$height=imagesy($image); $result['height']=$height=imagesy($image);
if (isset($imagemaxwidth) || isset($imagemaxheight)) if (isset($imagemaxwidth) || isset($imagemaxheight))
if (qa_image_constrain( if (qa_image_constrain(
$width, $height, $width, $height,
...@@ -175,30 +175,30 @@ ...@@ -175,30 +175,30 @@
$result['height']=$height; $result['height']=$height;
} }
} }
if (is_resource($image)) // might have been lost if (is_resource($image)) // might have been lost
imagedestroy($image); imagedestroy($image);
} }
} }
// Create the blob and return // Create the blob and return
require_once QA_INCLUDE_DIR.'qa-app-blobs.php'; require_once QA_INCLUDE_DIR.'qa-app-blobs.php';
$userid=qa_get_logged_in_userid(); $userid=qa_get_logged_in_userid();
$cookieid=isset($userid) ? qa_cookie_get() : qa_cookie_get_create(); $cookieid=isset($userid) ? qa_cookie_get() : qa_cookie_get_create();
$result['blobid']=qa_create_blob($content, $format, $sourcefilename, $userid, $cookieid, qa_remote_ip_address()); $result['blobid']=qa_create_blob($content, $format, $sourcefilename, $userid, $cookieid, qa_remote_ip_address());
if (!isset($result['blobid'])) { if (!isset($result['blobid'])) {
$result['error']=qa_lang('main/general_error'); $result['error']=qa_lang('main/general_error');
return $result; return $result;
} }
$result['bloburl']=qa_get_blob_url($result['blobid'], true); $result['bloburl']=qa_get_blob_url($result['blobid'], true);
return $result; return $result;
} }
function qa_upload_file_one($maxfilesize=null, $onlyimage=false, $imagemaxwidth=null, $imagemaxheight=null) function qa_upload_file_one($maxfilesize=null, $onlyimage=false, $imagemaxwidth=null, $imagemaxheight=null)
/* /*
...@@ -206,11 +206,11 @@ ...@@ -206,11 +206,11 @@
*/ */
{ {
$file=reset($_FILES); $file=reset($_FILES);
return qa_upload_file($file['tmp_name'], $file['name'], $maxfilesize, $onlyimage, $imagemaxwidth, $imagemaxheight); return qa_upload_file($file['tmp_name'], $file['name'], $maxfilesize, $onlyimage, $imagemaxwidth, $imagemaxheight);
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
*/ */
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-app-votes.php File: qa-include/qa-app-votes.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Handling incoming votes (application level) Description: Handling incoming votes (application level)
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -37,13 +37,13 @@ ...@@ -37,13 +37,13 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } 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. // 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(...) // 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-users.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php'; require_once QA_INCLUDE_DIR.'qa-app-limits.php';
if ( if (
is_array($post) && is_array($post) &&
( ($post['basetype']=='Q') || ($post['basetype']=='A') ) && ( ($post['basetype']=='Q') || ($post['basetype']=='A') ) &&
...@@ -51,37 +51,37 @@ ...@@ -51,37 +51,37 @@
( (!isset($post['userid'])) || (!isset($userid)) || ($post['userid']!=$userid) ) ( (!isset($post['userid'])) || (!isset($userid)) || ($post['userid']!=$userid) )
) { ) {
$permiterror=qa_user_post_permit_error(($post['basetype']=='Q') ? 'permit_vote_q' : 'permit_vote_a', $post, 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); $errordownonly=(!$permiterror) && ($vote<0);
if ($errordownonly) if ($errordownonly)
$permiterror=qa_user_post_permit_error('permit_vote_down', $post); $permiterror=qa_user_post_permit_error('permit_vote_down', $post);
switch ($permiterror) { switch ($permiterror) {
case 'login': case 'login':
return qa_insert_login_links(qa_lang_html('main/vote_must_login'), $topage); return qa_insert_login_links(qa_lang_html('main/vote_must_login'), $topage);
break; break;
case 'confirm': case 'confirm':
return qa_insert_login_links(qa_lang_html($errordownonly ? 'main/vote_down_must_confirm' : 'main/vote_must_confirm'), $topage); return qa_insert_login_links(qa_lang_html($errordownonly ? 'main/vote_down_must_confirm' : 'main/vote_must_confirm'), $topage);
break; break;
case 'limit': case 'limit':
return qa_lang_html('main/vote_limit'); return qa_lang_html('main/vote_limit');
break; break;
default: default:
return qa_lang_html('users/no_permission'); return qa_lang_html('users/no_permission');
break; break;
case false: case false:
return false; return false;
} }
} else } else
return qa_lang_html('main/vote_not_allowed'); // voting option should not have been presented (but could happen due to options change) return qa_lang_html('main/vote_not_allowed'); // voting option should not have been presented (but could happen due to options change)
} }
function qa_vote_set($post, $userid, $handle, $cookieid, $vote) function qa_vote_set($post, $userid, $handle, $cookieid, $vote)
/* /*
Actually set (application level) the $vote (-1/0/1) by $userid (with $handle and $cookieid) on $postid. Actually set (application level) the $vote (-1/0/1) by $userid (with $handle and $cookieid) on $postid.
...@@ -89,56 +89,56 @@ ...@@ -89,56 +89,56 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-db-points.php'; require_once QA_INCLUDE_DIR.'qa-db-points.php';
require_once QA_INCLUDE_DIR.'qa-db-hotness.php'; require_once QA_INCLUDE_DIR.'qa-db-hotness.php';
require_once QA_INCLUDE_DIR.'qa-db-votes.php'; require_once QA_INCLUDE_DIR.'qa-db-votes.php';
require_once QA_INCLUDE_DIR.'qa-db-post-create.php'; require_once QA_INCLUDE_DIR.'qa-db-post-create.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php'; require_once QA_INCLUDE_DIR.'qa-app-limits.php';
$vote=(int)min(1, max(-1, $vote)); $vote=(int)min(1, max(-1, $vote));
$oldvote=(int)qa_db_uservote_get($post['postid'], $userid); $oldvote=(int)qa_db_uservote_get($post['postid'], $userid);
qa_db_uservote_set($post['postid'], $userid, $vote); qa_db_uservote_set($post['postid'], $userid, $vote);
qa_db_post_recount_votes($post['postid']); qa_db_post_recount_votes($post['postid']);
$postisanswer=($post['basetype']=='A'); $postisanswer=($post['basetype']=='A');
if ($postisanswer) { if ($postisanswer) {
qa_db_post_acount_update($post['parentid']); qa_db_post_acount_update($post['parentid']);
qa_db_unupaqcount_update(); qa_db_unupaqcount_update();
} }
$columns=array(); $columns=array();
if ( ($vote>0) || ($oldvote>0) ) if ( ($vote>0) || ($oldvote>0) )
$columns[]=$postisanswer ? 'aupvotes' : 'qupvotes'; $columns[]=$postisanswer ? 'aupvotes' : 'qupvotes';
if ( ($vote<0) || ($oldvote<0) ) if ( ($vote<0) || ($oldvote<0) )
$columns[]=$postisanswer ? 'adownvotes' : 'qdownvotes'; $columns[]=$postisanswer ? 'adownvotes' : 'qdownvotes';
qa_db_points_update_ifuser($userid, $columns); qa_db_points_update_ifuser($userid, $columns);
qa_db_points_update_ifuser($post['userid'], array($postisanswer ? 'avoteds' : 'qvoteds', 'upvoteds', 'downvoteds')); qa_db_points_update_ifuser($post['userid'], array($postisanswer ? 'avoteds' : 'qvoteds', 'upvoteds', 'downvoteds'));
if ($post['basetype']=='Q') if ($post['basetype']=='Q')
qa_db_hotness_update($post['postid']); qa_db_hotness_update($post['postid']);
if ($vote<0) if ($vote<0)
$event=$postisanswer ? 'a_vote_down' : 'q_vote_down'; $event=$postisanswer ? 'a_vote_down' : 'q_vote_down';
elseif ($vote>0) elseif ($vote>0)
$event=$postisanswer ? 'a_vote_up' : 'q_vote_up'; $event=$postisanswer ? 'a_vote_up' : 'q_vote_up';
else else
$event=$postisanswer ? 'a_vote_nil' : 'q_vote_nil'; $event=$postisanswer ? 'a_vote_nil' : 'q_vote_nil';
qa_report_event($event, $userid, $handle, $cookieid, array( qa_report_event($event, $userid, $handle, $cookieid, array(
'postid' => $post['postid'], 'postid' => $post['postid'],
'vote' => $vote, 'vote' => $vote,
'oldvote' => $oldvote, 'oldvote' => $oldvote,
)); ));
} }
function qa_flag_error_html($post, $userid, $topage) function qa_flag_error_html($post, $userid, $topage)
/* /*
Check if $userid can flag $post, on the page $topage. Check if $userid can flag $post, on the page $topage.
...@@ -146,7 +146,7 @@ ...@@ -146,7 +146,7 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } 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. // 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(...) // Others ('approve', 'level') prevent the flag button being shown, in qa_page_q_post_rules(...)
...@@ -160,32 +160,32 @@ ...@@ -160,32 +160,32 @@
qa_opt('flagging_of_posts') && qa_opt('flagging_of_posts') &&
( (!isset($post['userid'])) || (!isset($userid)) || ($post['userid']!=$userid) ) ( (!isset($post['userid'])) || (!isset($userid)) || ($post['userid']!=$userid) )
) { ) {
switch (qa_user_post_permit_error('permit_flag', $post, QA_LIMIT_FLAGS)) { switch (qa_user_post_permit_error('permit_flag', $post, QA_LIMIT_FLAGS)) {
case 'login': case 'login':
return qa_insert_login_links(qa_lang_html('question/flag_must_login'), $topage); return qa_insert_login_links(qa_lang_html('question/flag_must_login'), $topage);
break; break;
case 'confirm': case 'confirm':
return qa_insert_login_links(qa_lang_html('question/flag_must_confirm'), $topage); return qa_insert_login_links(qa_lang_html('question/flag_must_confirm'), $topage);
break; break;
case 'limit': case 'limit':
return qa_lang_html('question/flag_limit'); return qa_lang_html('question/flag_limit');
break; break;
default: default:
return qa_lang_html('users/no_permission'); return qa_lang_html('users/no_permission');
break; break;
case false: case false:
return false; return false;
} }
} else } else
return qa_lang_html('question/flag_not_allowed'); // flagging option should not have been presented return qa_lang_html('question/flag_not_allowed'); // flagging option should not have been presented
} }
function qa_flag_set_tohide($oldpost, $userid, $handle, $cookieid, $question) function qa_flag_set_tohide($oldpost, $userid, $handle, $cookieid, $question)
/* /*
...@@ -195,20 +195,20 @@ ...@@ -195,20 +195,20 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-db-votes.php'; require_once QA_INCLUDE_DIR.'qa-db-votes.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php'; require_once QA_INCLUDE_DIR.'qa-app-limits.php';
require_once QA_INCLUDE_DIR.'qa-db-post-update.php'; require_once QA_INCLUDE_DIR.'qa-db-post-update.php';
qa_db_userflag_set($oldpost['postid'], $userid, true); qa_db_userflag_set($oldpost['postid'], $userid, true);
qa_db_post_recount_flags($oldpost['postid']); qa_db_post_recount_flags($oldpost['postid']);
qa_db_flaggedcount_update(); qa_db_flaggedcount_update();
switch ($oldpost['basetype']) { switch ($oldpost['basetype']) {
case 'Q': case 'Q':
$event='q_flag'; $event='q_flag';
break; break;
case 'A': case 'A':
$event='a_flag'; $event='a_flag';
break; break;
...@@ -217,9 +217,9 @@ ...@@ -217,9 +217,9 @@
$event='c_flag'; $event='c_flag';
break; break;
} }
$post=qa_db_select_with_pending(qa_db_full_post_selectspec(null, $oldpost['postid'])); $post=qa_db_select_with_pending(qa_db_full_post_selectspec(null, $oldpost['postid']));
qa_report_event($event, $userid, $handle, $cookieid, array( qa_report_event($event, $userid, $handle, $cookieid, array(
'postid' => $oldpost['postid'], 'postid' => $oldpost['postid'],
'oldpost' => $oldpost, 'oldpost' => $oldpost,
...@@ -227,7 +227,7 @@ ...@@ -227,7 +227,7 @@
'questionid' => $question['postid'], 'questionid' => $question['postid'],
'question' => $question, 'question' => $question,
)); ));
return ($post['flagcount']>=qa_opt('flagging_hide_after')) && !$post['hidden']; return ($post['flagcount']>=qa_opt('flagging_hide_after')) && !$post['hidden'];
} }
...@@ -239,20 +239,20 @@ ...@@ -239,20 +239,20 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-db-votes.php'; require_once QA_INCLUDE_DIR.'qa-db-votes.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php'; require_once QA_INCLUDE_DIR.'qa-app-limits.php';
require_once QA_INCLUDE_DIR.'qa-db-post-update.php'; require_once QA_INCLUDE_DIR.'qa-db-post-update.php';
qa_db_userflag_set($oldpost['postid'], $userid, false); qa_db_userflag_set($oldpost['postid'], $userid, false);
qa_db_post_recount_flags($oldpost['postid']); qa_db_post_recount_flags($oldpost['postid']);
qa_db_flaggedcount_update(); qa_db_flaggedcount_update();
switch ($oldpost['basetype']) { switch ($oldpost['basetype']) {
case 'Q': case 'Q':
$event='q_unflag'; $event='q_unflag';
break; break;
case 'A': case 'A':
$event='a_unflag'; $event='a_unflag';
break; break;
...@@ -261,14 +261,14 @@ ...@@ -261,14 +261,14 @@
$event='c_unflag'; $event='c_unflag';
break; break;
} }
qa_report_event($event, $userid, $handle, $cookieid, array( qa_report_event($event, $userid, $handle, $cookieid, array(
'postid' => $oldpost['postid'], 'postid' => $oldpost['postid'],
'oldpost' => $oldpost, 'oldpost' => $oldpost,
)); ));
} }
function qa_flags_clear_all($oldpost, $userid, $handle, $cookieid) function qa_flags_clear_all($oldpost, $userid, $handle, $cookieid)
/* /*
Clear (application level) all flags on $oldpost by $userid (with $handle and $cookieid). Clear (application level) all flags on $oldpost by $userid (with $handle and $cookieid).
...@@ -276,11 +276,11 @@ ...@@ -276,11 +276,11 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
require_once QA_INCLUDE_DIR.'qa-db-votes.php'; require_once QA_INCLUDE_DIR.'qa-db-votes.php';
require_once QA_INCLUDE_DIR.'qa-app-limits.php'; require_once QA_INCLUDE_DIR.'qa-app-limits.php';
require_once QA_INCLUDE_DIR.'qa-db-post-update.php'; require_once QA_INCLUDE_DIR.'qa-db-post-update.php';
qa_db_userflags_clear_all($oldpost['postid']); qa_db_userflags_clear_all($oldpost['postid']);
qa_db_post_recount_flags($oldpost['postid']); qa_db_post_recount_flags($oldpost['postid']);
qa_db_flaggedcount_update(); qa_db_flaggedcount_update();
...@@ -289,7 +289,7 @@ ...@@ -289,7 +289,7 @@
case 'Q': case 'Q':
$event='q_clearflags'; $event='q_clearflags';
break; break;
case 'A': case 'A':
$event='a_clearflags'; $event='a_clearflags';
break; break;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-blob.php File: qa-include/qa-blob.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Response to blob requests, outputting blob from the database Description: Response to blob requests, outputting blob from the database
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
header('HTTP/1.1 500 Internal Server Error'); header('HTTP/1.1 500 Internal Server Error');
qa_exit('error'); qa_exit('error');
} }
// Load the Q2A base file which sets up a bunch of crucial stuff // Load the Q2A base file which sets up a bunch of crucial stuff
...@@ -48,44 +48,44 @@ ...@@ -48,44 +48,44 @@
require_once QA_INCLUDE_DIR.'qa-app-blobs.php'; require_once QA_INCLUDE_DIR.'qa-app-blobs.php';
qa_db_connect('qa_blob_db_fail_handler'); qa_db_connect('qa_blob_db_fail_handler');
$blob=qa_read_blob(qa_get('qa_blobid')); $blob=qa_read_blob(qa_get('qa_blobid'));
if (isset($blob)) { if (isset($blob)) {
header('Cache-Control: max-age=2592000, public'); // allows browsers and proxies to cache the blob header('Cache-Control: max-age=2592000, public'); // allows browsers and proxies to cache the blob
switch ($blob['format']) { switch ($blob['format']) {
case 'jpeg': case 'jpeg':
case 'jpg': case 'jpg':
header('Content-Type: image/jpeg'); header('Content-Type: image/jpeg');
break; break;
case 'gif': case 'gif':
header('Content-Type: image/gif'); header('Content-Type: image/gif');
break; break;
case 'png': case 'png':
header('Content-Type: image/png'); header('Content-Type: image/png');
break; break;
case 'swf': case 'swf':
header('Content-Type: application/x-shockwave-flash'); header('Content-Type: application/x-shockwave-flash');
break; break;
default: default:
$filename=preg_replace('/[^A-Za-z0-9 \\._-]/', '-', $blob['filename']); // for compatibility with HTTP headers and all browsers $filename=preg_replace('/[^A-Za-z0-9 \\._-]/', '-', $blob['filename']); // for compatibility with HTTP headers and all browsers
header('Content-Type: application/octet-stream'); header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$filename.'"'); header('Content-Disposition: attachment; filename="'.$filename.'"');
break; break;
} }
echo $blob['content']; echo $blob['content'];
} else } else
header('HTTP/1.0 404 Not Found'); header('HTTP/1.0 404 Not Found');
qa_db_disconnect(); qa_db_disconnect();
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-check-lang.php File: qa-include/qa-check-lang.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Development tool to see which language phrases are missing or unused Description: Development tool to see which language phrases are missing or unused
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -28,10 +28,10 @@ ...@@ -28,10 +28,10 @@
require 'qa-base.php'; require 'qa-base.php';
require_once QA_INCLUDE_DIR.'qa-app-users.php'; require_once QA_INCLUDE_DIR.'qa-app-users.php';
if (qa_get_logged_in_level() < QA_USER_LEVEL_ADMIN) if (qa_get_logged_in_level() < QA_USER_LEVEL_ADMIN)
qa_redirect('admin/general', null, qa_opt('site_url')); qa_redirect('admin/general', null, qa_opt('site_url'));
header('Content-type: text/html; charset=utf-8'); header('Content-type: text/html; charset=utf-8');
?> ?>
<html> <html>
...@@ -52,17 +52,17 @@ ...@@ -52,17 +52,17 @@
if (preg_match_all('/\^(([0-9]+)|([a-z_]+)|)/', $phrase, $matches)) if (preg_match_all('/\^(([0-9]+)|([a-z_]+)|)/', $phrase, $matches))
foreach ($matches[0] as $match) foreach ($matches[0] as $match)
@$substitutions[$match]++; @$substitutions[$match]++;
return $substitutions; return $substitutions;
} }
echo '<font color="#cc0000"><code>Dark red = important to review.</code></font><br>'; echo '<font color="#cc0000"><code>Dark red = important to review.</code></font><br>';
echo '<font color="#cc9999"><code>Light red = probably safe to ignore.</code></font>'; echo '<font color="#cc9999"><code>Light red = probably safe to ignore.</code></font>';
echo '<h1>Checking US English files in <code>qa-include</code>...</h1>'; echo '<h1>Checking US English files in <code>qa-include</code>...</h1>';
$includefiles=array_merge(glob(QA_INCLUDE_DIR.'qa-*.php'), glob(QA_PLUGIN_DIR.'*/qa-*.php')); $includefiles=array_merge(glob(QA_INCLUDE_DIR.'qa-*.php'), glob(QA_PLUGIN_DIR.'*/qa-*.php'));
$definite=array(); $definite=array();
$probable=array(); $probable=array();
$possible=array(); $possible=array();
...@@ -70,14 +70,14 @@ ...@@ -70,14 +70,14 @@
$english=array(); $english=array();
$backmap=array(); $backmap=array();
$substitutions=array(); $substitutions=array();
output_start_includes(); output_start_includes();
foreach ($includefiles as $includefile) { foreach ($includefiles as $includefile) {
$contents=file_get_contents($includefile); $contents=file_get_contents($includefile);
preg_match_all('/qa_lang[a-z_]*\s*\(\s*[\'\"]([a-z]+)\/([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER); preg_match_all('/qa_lang[a-z_]*\s*\(\s*[\'\"]([a-z]+)\/([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER);
foreach ($matches as $matchparts) foreach ($matches as $matchparts)
if ($matchparts[2]=='date_month_') { // special case for month names if ($matchparts[2]=='date_month_') { // special case for month names
for ($month=1; $month<=12; $month++) for ($month=1; $month<=12; $month++)
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
} else } else
@$definite[$matchparts[1]][$matchparts[2]]++; @$definite[$matchparts[1]][$matchparts[2]]++;
preg_match_all('/[\'\"]([a-z]+)\/([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER); preg_match_all('/[\'\"]([a-z]+)\/([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER);
foreach ($matches as $matchparts) foreach ($matches as $matchparts)
...@@ -93,10 +93,10 @@ ...@@ -93,10 +93,10 @@
if (preg_match('|/qa-include/qa-lang-([a-z]+)\.php$|', $includefile, $matches)) { // it's a lang file if (preg_match('|/qa-include/qa-lang-([a-z]+)\.php$|', $includefile, $matches)) { // it's a lang file
$prefix=$matches[1]; $prefix=$matches[1];
output_reading_include($includefile); output_reading_include($includefile);
$phrases=@include $includefile; $phrases=@include $includefile;
foreach ($phrases as $key => $value) { foreach ($phrases as $key => $value) {
@$defined[$prefix][$key]++; @$defined[$prefix][$key]++;
$english[$prefix][$key]=$value; $english[$prefix][$key]=$value;
...@@ -106,69 +106,69 @@ ...@@ -106,69 +106,69 @@
} else { // it's a different file } else { // it's a different file
preg_match_all('/[\'\"\/]([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER); preg_match_all('/[\'\"\/]([0-9a-z_]+)[\'\"]/', $contents, $matches, PREG_SET_ORDER);
foreach ($matches as $matchparts) foreach ($matches as $matchparts)
@$possible[$matchparts[1]]++; @$possible[$matchparts[1]]++;
} }
} }
output_finish_includes(); output_finish_includes();
foreach ($definite as $key => $valuecount) foreach ($definite as $key => $valuecount)
foreach ($valuecount as $value => $count) foreach ($valuecount as $value => $count)
if (!@$defined[$key][$value]) if (!@$defined[$key][$value])
output_lang_issue($key, $value, 'used by '.$count.' file/s but not defined'); output_lang_issue($key, $value, 'used by '.$count.' file/s but not defined');
foreach ($defined as $key => $valuecount) foreach ($defined as $key => $valuecount)
foreach ($valuecount as $value => $count) foreach ($valuecount as $value => $count)
if ( (!@$definite[$key][$value]) && (!@$probable[$key][$value]) && (!@$possible[$value]) ) if ( (!@$definite[$key][$value]) && (!@$probable[$key][$value]) && (!@$possible[$value]) )
output_lang_issue($key, $value, 'defined but apparently not used'); output_lang_issue($key, $value, 'defined but apparently not used');
foreach ($backmap as $phrase => $where) foreach ($backmap as $phrase => $where)
if (count($where)>1) if (count($where)>1)
foreach ($where as $onewhere) foreach ($where as $onewhere)
output_lang_issue($onewhere['prefix'], $onewhere['key'], 'contains the shared phrase "'.$phrase.'"', false); output_lang_issue($onewhere['prefix'], $onewhere['key'], 'contains the shared phrase "'.$phrase.'"', false);
require_once QA_INCLUDE_DIR.'qa-app-admin.php'; require_once QA_INCLUDE_DIR.'qa-app-admin.php';
$languages=qa_admin_language_options(); $languages=qa_admin_language_options();
unset($languages['']); unset($languages['']);
foreach ($languages as $code => $language) { foreach ($languages as $code => $language) {
echo '<h1>Checking '.$language.' files in <code>qa-lang/'.$code.'</code>...</h1>'; echo '<h1>Checking '.$language.' files in <code>qa-lang/'.$code.'</code>...</h1>';
$langdefined=array(); $langdefined=array();
$langdifferent=array(); $langdifferent=array();
$langsubstitutions=array(); $langsubstitutions=array();
$langincludefiles=glob(QA_LANG_DIR.$code.'/qa-*.php'); $langincludefiles=glob(QA_LANG_DIR.$code.'/qa-*.php');
$langnewphrases=array(); $langnewphrases=array();
output_start_includes(); output_start_includes();
foreach ($langincludefiles as $langincludefile) foreach ($langincludefiles as $langincludefile)
if (preg_match('/qa-lang-([a-z]+)\.php$/', $langincludefile, $matches)) { // it's a lang file if (preg_match('/qa-lang-([a-z]+)\.php$/', $langincludefile, $matches)) { // it's a lang file
$prefix=$matches[1]; $prefix=$matches[1];
output_reading_include($langincludefile); output_reading_include($langincludefile);
$phrases=@include $langincludefile; $phrases=@include $langincludefile;
foreach ($phrases as $key => $value) { foreach ($phrases as $key => $value) {
@$langdefined[$prefix][$key]++; @$langdefined[$prefix][$key]++;
$langdifferent[$prefix][$key]=($value!=@$english[$prefix][$key]); $langdifferent[$prefix][$key]=($value!=@$english[$prefix][$key]);
$langsubstitutions[$prefix][$key]=get_phrase_substitutions($value); $langsubstitutions[$prefix][$key]=get_phrase_substitutions($value);
} }
} }
output_finish_includes(); output_finish_includes();
foreach ($langdefined as $key => $valuecount) foreach ($langdefined as $key => $valuecount)
foreach ($valuecount as $value => $count) { foreach ($valuecount as $value => $count) {
if (!@$defined[$key][$value]) if (!@$defined[$key][$value])
output_lang_issue($key, $value, 'defined but not in US English files'); output_lang_issue($key, $value, 'defined but not in US English files');
elseif (!$langdifferent[$key][$value]) elseif (!$langdifferent[$key][$value])
output_lang_issue($key, $value, 'identical to US English files', false); output_lang_issue($key, $value, 'identical to US English files', false);
else else
foreach ($substitutions[$key][$value] as $substitution => $subcount) foreach ($substitutions[$key][$value] as $substitution => $subcount)
if (!@$langsubstitutions[$key][$value][$substitution]) if (!@$langsubstitutions[$key][$value][$substitution])
...@@ -176,10 +176,10 @@ ...@@ -176,10 +176,10 @@
elseif ($subcount > @$langsubstitutions[$key][$value][$substitution]) elseif ($subcount > @$langsubstitutions[$key][$value][$substitution])
output_lang_issue($key, $value, 'has fewer of the substitution '.$substitution); output_lang_issue($key, $value, 'has fewer of the substitution '.$substitution);
} }
foreach ($defined as $key => $valuecount) { foreach ($defined as $key => $valuecount) {
$showaserror=!(($key=='admin') || ($key=='options') || ($code=='en-GB')); $showaserror=!(($key=='admin') || ($key=='options') || ($code=='en-GB'));
if (@$langdefined[$key]) { if (@$langdefined[$key]) {
if (count($langdefined[$key]) < (count($valuecount)/2)) { // only a few phrases defined if (count($langdefined[$key]) < (count($valuecount)/2)) { // only a few phrases defined
output_lang_issue($key, null, 'few translations provided so will use US English defaults', $showaserror); output_lang_issue($key, null, 'few translations provided so will use US English defaults', $showaserror);
...@@ -193,22 +193,22 @@ ...@@ -193,22 +193,22 @@
} else } else
output_lang_issue($key, null, 'no translations provided so will use US English defaults', $showaserror); output_lang_issue($key, null, 'no translations provided so will use US English defaults', $showaserror);
} }
foreach ($langnewphrases as $prefix => $phrases) { foreach ($langnewphrases as $prefix => $phrases) {
echo '<h2>'.$language.' phrases to add to <code>qa-lang/'.$code.'/qa-lang-'.$prefix.'.php</code>:</h2>'; echo '<h2>'.$language.' phrases to add to <code>qa-lang/'.$code.'/qa-lang-'.$prefix.'.php</code>:</h2>';
echo 'Copy and paste this into the middle of <code>qa-lang/'.$code.'/qa-lang-'.$prefix.'.php</code> then translate the right-hand side after the <code>=></code> symbol.'; echo 'Copy and paste this into the middle of <code>qa-lang/'.$code.'/qa-lang-'.$prefix.'.php</code> then translate the right-hand side after the <code>=></code> symbol.';
echo '<pre>'; echo '<pre>';
foreach ($phrases as $key => $value) foreach ($phrases as $key => $value)
echo '<span style="font-size:25%;">'."\t\t</span>'".$key."' => \"".strtr($value, array('\\' => '\\\\', '"' => '\"', '$' => '\$', "\n" => '\n', "\t" => '\t'))."\",\n"; echo '<span style="font-size:25%;">'."\t\t</span>'".$key."' => \"".strtr($value, array('\\' => '\\\\', '"' => '\"', '$' => '\$', "\n" => '\n', "\t" => '\t'))."\",\n";
echo '</pre>'; echo '</pre>';
} }
} }
function output_lang_issue($prefix, $key, $issue, $error=true) function output_lang_issue($prefix, $key, $issue, $error=true)
{ {
echo '<font color="'.($error ? '#cc0000' : '#cc9999').'"><code>'; echo '<font color="'.($error ? '#cc0000' : '#cc9999').'"><code>';
...@@ -217,7 +217,7 @@ ...@@ -217,7 +217,7 @@
if (strlen($key)) if (strlen($key))
echo "'<b>".qa_html($key)."</b>'"; echo "'<b>".qa_html($key)."</b>'";
echo '</code></font> &nbsp; '.qa_html($issue).'<br>'; echo '</code></font> &nbsp; '.qa_html($issue).'<br>';
} }
...@@ -225,30 +225,30 @@ ...@@ -225,30 +225,30 @@
function output_start_includes() function output_start_includes()
{ {
global $oneread; global $oneread;
$oneread=false; $oneread=false;
echo '<p style="font-size:80%; color:#999;">Reading: '; echo '<p style="font-size:80%; color:#999;">Reading: ';
} }
function output_reading_include($file) function output_reading_include($file)
{ {
global $oneread; global $oneread;
echo ($oneread ? ', ' : '').htmlspecialchars(basename($file)); echo ($oneread ? ', ' : '').htmlspecialchars(basename($file));
flush(); flush();
$oneread=true; $oneread=true;
} }
function output_finish_includes() function output_finish_includes()
{ {
echo '</p>'; echo '</p>';
} }
echo '<h1>Finished scanning for problems!</h1>'; echo '<h1>Finished scanning for problems!</h1>';
?> ?>
......
<?php <?php
/* /*
Question2Answer (c) Gideon Greenspan Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-db-blobs.php File: qa-include/qa-db-blobs.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Database-level access to blobs table for large chunks of data (e.g. images) Description: Database-level access to blobs table for large chunks of data (e.g. images)
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -32,14 +32,14 @@ ...@@ -32,14 +32,14 @@
function qa_db_blob_create($content, $format, $sourcefilename=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, other fields as provided Create a new blob in the database with $content and $format, other fields as provided
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
for ($attempt=0; $attempt<10; $attempt++) { for ($attempt=0; $attempt<10; $attempt++) {
$blobid=qa_db_random_bigint(); $blobid=qa_db_random_bigint();
if (qa_db_blob_exists($blobid)) if (qa_db_blob_exists($blobid))
continue; continue;
...@@ -47,28 +47,28 @@ ...@@ -47,28 +47,28 @@
'INSERT INTO ^blobs (blobid, format, content, filename, userid, cookieid, createip, created) VALUES (#, $, $, $, $, #, INET_ATON($), NOW())', 'INSERT INTO ^blobs (blobid, format, content, filename, userid, cookieid, createip, created) VALUES (#, $, $, $, $, #, INET_ATON($), NOW())',
$blobid, $format, $content, $sourcefilename, $userid, $cookieid, $ip $blobid, $format, $content, $sourcefilename, $userid, $cookieid, $ip
); );
return $blobid; return $blobid;
} }
return null; return null;
} }
function qa_db_blob_read($blobid) function qa_db_blob_read($blobid)
/* /*
Get the information about blob $blobid from the database Get the information about blob $blobid from the database
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return qa_db_read_one_assoc(qa_db_query_sub( return qa_db_read_one_assoc(qa_db_query_sub(
'SELECT content, format, filename FROM ^blobs WHERE blobid=#', 'SELECT content, format, filename FROM ^blobs WHERE blobid=#',
$blobid $blobid
), true); ), true);
} }
function qa_db_blob_set_content($blobid, $content) function qa_db_blob_set_content($blobid, $content)
/* /*
Change the content of blob $blobid in the database to $content (can also be null) Change the content of blob $blobid in the database to $content (can also be null)
...@@ -79,29 +79,29 @@ ...@@ -79,29 +79,29 @@
$content, $blobid $content, $blobid
); );
} }
function qa_db_blob_delete($blobid) function qa_db_blob_delete($blobid)
/* /*
Delete blob $blobid in the database Delete blob $blobid in the database
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^blobs WHERE blobid=#', 'DELETE FROM ^blobs WHERE blobid=#',
$blobid $blobid
); );
} }
function qa_db_blob_exists($blobid) function qa_db_blob_exists($blobid)
/* /*
Check if blob $blobid exists in the database Check if blob $blobid exists in the database
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
return qa_db_read_one_value(qa_db_query_sub( return qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^blobs WHERE blobid=#', 'SELECT COUNT(*) FROM ^blobs WHERE blobid=#',
$blobid $blobid
......
<?php <?php
/* /*
Question2Answer (c) Gideon Greenspan Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-db-cache.php File: qa-include/qa-db-cache.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Database-level access to cache table Description: Database-level access to cache table
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^cache WHERE lastread<NOW()-INTERVAL # SECOND', 'DELETE FROM ^cache WHERE lastread<NOW()-INTERVAL # SECOND',
QA_DB_MAX_CACHE_AGE QA_DB_MAX_CACHE_AGE
...@@ -49,29 +49,29 @@ ...@@ -49,29 +49,29 @@
$type, $cacheid, $content $type, $cacheid, $content
); );
} }
function qa_db_cache_get($type, $cacheid) function qa_db_cache_get($type, $cacheid)
/* /*
Retrieve the item ($type, $cacheid) from the database cache table Retrieve the item ($type, $cacheid) from the database cache table
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
$content=qa_db_read_one_value(qa_db_query_sub( $content=qa_db_read_one_value(qa_db_query_sub(
'SELECT content FROM ^cache WHERE type=$ AND cacheid=#', 'SELECT content FROM ^cache WHERE type=$ AND cacheid=#',
$type, $cacheid $type, $cacheid
), true); ), true);
if (isset($content)) if (isset($content))
qa_db_query_sub( qa_db_query_sub(
'UPDATE ^cache SET lastread=NOW() WHERE type=$ AND cacheid=#', 'UPDATE ^cache SET lastread=NOW() WHERE type=$ AND cacheid=#',
$type, $cacheid $type, $cacheid
); );
return $content; return $content;
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
......
<?php <?php
/* /*
Question2Answer (c) Gideon Greenspan Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-db-cookies.php File: qa-include/qa-db-cookies.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Database access functions for user cookies Description: Database access functions for user cookies
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
{ {
for ($attempt=0; $attempt<10; $attempt++) { for ($attempt=0; $attempt<10; $attempt++) {
$cookieid=qa_db_random_bigint(); $cookieid=qa_db_random_bigint();
if (qa_db_cookie_exists($cookieid)) if (qa_db_cookie_exists($cookieid))
continue; continue;
...@@ -46,14 +46,14 @@ ...@@ -46,14 +46,14 @@
'VALUES (#, NOW(), COALESCE(INET_ATON($), 0))', 'VALUES (#, NOW(), COALESCE(INET_ATON($), 0))',
$cookieid, $ipaddress $cookieid, $ipaddress
); );
return $cookieid; return $cookieid;
} }
return null; return null;
} }
function qa_db_cookie_written($cookieid, $ipaddress) function qa_db_cookie_written($cookieid, $ipaddress)
/* /*
Note in database that a write operation has been done by user identified by $cookieid and from $ipaddress Note in database that a write operation has been done by user identified by $cookieid and from $ipaddress
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
); );
} }
function qa_db_cookie_exists($cookieid) function qa_db_cookie_exists($cookieid)
/* /*
Return whether $cookieid exists in database Return whether $cookieid exists in database
......
<?php <?php
/* /*
Question2Answer (c) Gideon Greenspan Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-db-events.php File: qa-include/qa-db-events.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Database-level access to userevents and sharedevents tables Description: Database-level access to userevents and sharedevents tables
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -41,77 +41,77 @@ ...@@ -41,77 +41,77 @@
{ {
require_once QA_INCLUDE_DIR.'qa-db-maxima.php'; require_once QA_INCLUDE_DIR.'qa-db-maxima.php';
require_once QA_INCLUDE_DIR.'qa-app-updates.php'; require_once QA_INCLUDE_DIR.'qa-app-updates.php';
$updatedsql=isset($timestamp) ? ('FROM_UNIXTIME('.qa_db_argument_to_mysql($timestamp, false).')') : 'NOW()'; $updatedsql=isset($timestamp) ? ('FROM_UNIXTIME('.qa_db_argument_to_mysql($timestamp, false).')') : 'NOW()';
// Enter it into the appropriate shared event stream for that entity // Enter it into the appropriate shared event stream for that entity
qa_db_query_sub( qa_db_query_sub(
'INSERT INTO ^sharedevents (entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) '. 'INSERT INTO ^sharedevents (entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) '.
'VALUES ($, #, #, #, $, $, '.$updatedsql.')', 'VALUES ($, #, #, #, $, $, '.$updatedsql.')',
$entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid $entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid
); );
// If this is for a question entity, check the shared event stream doesn't have too many entries for that question // If this is for a question entity, check the shared event stream doesn't have too many entries for that question
$questiontruncated=false; $questiontruncated=false;
if ($entitytype==QA_ENTITY_QUESTION) { if ($entitytype==QA_ENTITY_QUESTION) {
$truncate=qa_db_read_one_value(qa_db_query_sub( $truncate=qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^sharedevents WHERE entitytype=$ AND entityid=# AND questionid=# ORDER BY updated DESC LIMIT #,1', 'SELECT updated FROM ^sharedevents WHERE entitytype=$ AND entityid=# AND questionid=# ORDER BY updated DESC LIMIT #,1',
$entitytype, $entityid, $questionid, QA_DB_MAX_EVENTS_PER_Q $entitytype, $entityid, $questionid, QA_DB_MAX_EVENTS_PER_Q
), true); ), true);
if (isset($truncate)) { if (isset($truncate)) {
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^sharedevents WHERE entitytype=$ AND entityid=# AND questionid=# AND updated<=$', 'DELETE FROM ^sharedevents WHERE entitytype=$ AND entityid=# AND questionid=# AND updated<=$',
$entitytype, $entityid, $questionid, $truncate $entitytype, $entityid, $questionid, $truncate
); );
$questiontruncated=true; $questiontruncated=true;
} }
} }
// If we didn't truncate due to a specific question, truncate the shared event stream for its overall length // If we didn't truncate due to a specific question, truncate the shared event stream for its overall length
if (!$questiontruncated) { if (!$questiontruncated) {
$truncate=qa_db_read_one_value(qa_db_query_sub( $truncate=qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^sharedevents WHERE entitytype=$ AND entityid=$ ORDER BY updated DESC LIMIT #,1', 'SELECT updated FROM ^sharedevents WHERE entitytype=$ AND entityid=$ ORDER BY updated DESC LIMIT #,1',
$entitytype, $entityid, (int)qa_opt('max_store_user_updates') $entitytype, $entityid, (int)qa_opt('max_store_user_updates')
), true); ), true);
if (isset($truncate)) if (isset($truncate))
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^sharedevents WHERE entitytype=$ AND entityid=$ AND updated<=$', 'DELETE FROM ^sharedevents WHERE entitytype=$ AND entityid=$ AND updated<=$',
$entitytype, $entityid, $truncate $entitytype, $entityid, $truncate
); );
} }
// See if we can identify a user who has favorited this entity, but is not using its shared event stream // See if we can identify a user who has favorited this entity, but is not using its shared event stream
$randomuserid=qa_db_read_one_value(qa_db_query_sub( $randomuserid=qa_db_read_one_value(qa_db_query_sub(
'SELECT userid FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents=0 ORDER BY RAND() LIMIT 1', 'SELECT userid FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents=0 ORDER BY RAND() LIMIT 1',
$entitytype, $entityid $entitytype, $entityid
), true); ), true);
if (isset($randomuserid)) { if (isset($randomuserid)) {
// If one was found, this means we have one or more individual event streams, so update them all // If one was found, this means we have one or more individual event streams, so update them all
qa_db_query_sub( qa_db_query_sub(
'INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) '. 'INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) '.
'SELECT userid, $, #, #, #, $, $, '.$updatedsql.' FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents=0', 'SELECT userid, $, #, #, #, $, $, '.$updatedsql.' FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents=0',
$entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid, $entitytype, $entityid $entitytype, $entityid, $questionid, $lastpostid, $updatetype, $lastuserid, $entitytype, $entityid
); );
// Now truncate the random individual event stream that was found earlier // Now truncate the random individual event stream that was found earlier
// (in theory we should truncate them all, but truncation is just a 'housekeeping' activity, so it's not necessary) // (in theory we should truncate them all, but truncation is just a 'housekeeping' activity, so it's not necessary)
qa_db_user_events_truncate($randomuserid, $questionid); qa_db_user_events_truncate($randomuserid, $questionid);
} }
} }
function qa_db_event_create_not_entity($userid, $questionid, $lastpostid, $updatetype, $lastuserid, $timestamp=null) function qa_db_event_create_not_entity($userid, $questionid, $lastpostid, $updatetype, $lastuserid, $timestamp=null)
/* /*
Add an event to the event stream for $userid which is not related to an entity they are following (but rather a Add an event to the event stream for $userid which is not related to an entity they are following (but rather a
...@@ -123,52 +123,52 @@ ...@@ -123,52 +123,52 @@
require_once QA_INCLUDE_DIR.'qa-app-updates.php'; require_once QA_INCLUDE_DIR.'qa-app-updates.php';
$updatedsql=isset($timestamp) ? ('FROM_UNIXTIME('.qa_db_argument_to_mysql($timestamp, false).')') : 'NOW()'; $updatedsql=isset($timestamp) ? ('FROM_UNIXTIME('.qa_db_argument_to_mysql($timestamp, false).')') : 'NOW()';
qa_db_query_sub( qa_db_query_sub(
"INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) ". "INSERT INTO ^userevents (userid, entitytype, entityid, questionid, lastpostid, updatetype, lastuserid, updated) ".
"VALUES ($, $, 0, #, #, $, $, ".$updatedsql.")", "VALUES ($, $, 0, #, #, $, $, ".$updatedsql.")",
$userid, QA_ENTITY_NONE, $questionid, $lastpostid, $updatetype, $lastuserid $userid, QA_ENTITY_NONE, $questionid, $lastpostid, $updatetype, $lastuserid
); );
qa_db_user_events_truncate($userid, $questionid); qa_db_user_events_truncate($userid, $questionid);
} }
function qa_db_user_events_truncate($userid, $questionid=null) function qa_db_user_events_truncate($userid, $questionid=null)
/* /*
Trim the number of events in the event stream for $userid. If an event was just added for a particular question, Trim the number of events in the event stream for $userid. If an event was just added for a particular question,
pass the question's id in $questionid (to help focus the truncation). pass the question's id in $questionid (to help focus the truncation).
*/ */
{ {
// First try truncating based on there being too many events for this question // First try truncating based on there being too many events for this question
$questiontruncated=false; $questiontruncated=false;
if (isset($questionid)) { if (isset($questionid)) {
$truncate=qa_db_read_one_value(qa_db_query_sub( $truncate=qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^userevents WHERE userid=$ AND questionid=# ORDER BY updated DESC LIMIT #,1', 'SELECT updated FROM ^userevents WHERE userid=$ AND questionid=# ORDER BY updated DESC LIMIT #,1',
$userid, $questionid, QA_DB_MAX_EVENTS_PER_Q $userid, $questionid, QA_DB_MAX_EVENTS_PER_Q
), true); ), true);
if (isset($truncate)) { if (isset($truncate)) {
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^userevents WHERE userid=$ AND questionid=# AND updated<=$', 'DELETE FROM ^userevents WHERE userid=$ AND questionid=# AND updated<=$',
$userid, $questionid, $truncate $userid, $questionid, $truncate
); );
$questiontruncated=true; $questiontruncated=true;
} }
} }
// If that didn't happen, try truncating the stream in general based on its total length // If that didn't happen, try truncating the stream in general based on its total length
if (!$questiontruncated) { if (!$questiontruncated) {
$truncate=qa_db_read_one_value(qa_db_query_sub( $truncate=qa_db_read_one_value(qa_db_query_sub(
'SELECT updated FROM ^userevents WHERE userid=$ ORDER BY updated DESC LIMIT #,1', 'SELECT updated FROM ^userevents WHERE userid=$ ORDER BY updated DESC LIMIT #,1',
$userid, (int)qa_opt('max_store_user_updates') $userid, (int)qa_opt('max_store_user_updates')
), true); ), true);
if (isset($truncate)) if (isset($truncate))
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^userevents WHERE userid=$ AND updated<=$', 'DELETE FROM ^userevents WHERE userid=$ AND updated<=$',
......
<?php <?php
/* /*
Question2Answer (c) Gideon Greenspan Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-db-favorites.php File: qa-include/qa-db-favorites.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Database-level access to userfavorites table Description: Database-level access to userfavorites table
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -53,11 +53,11 @@ ...@@ -53,11 +53,11 @@
background to manage the queuing and transport of these messages from publishers (event streams) to subscribers background to manage the queuing and transport of these messages from publishers (event streams) to subscribers
(users' lists of news updates). While we could have a cron-style process to manage this, I'm avoiding it for as long (users' lists of news updates). While we could have a cron-style process to manage this, I'm avoiding it for as long
as possible since it complicates setup. It also means there can be delays in updating users' news feeds. as possible since it complicates setup. It also means there can be delays in updating users' news feeds.
So instead we adopt a hybrid approach. For each event created in an entity's stream, we record a single copy of that So instead we adopt a hybrid approach. For each event created in an entity's stream, we record a single copy of that
event in the entity's stream in the qa_sharedevents table. In addition, by default, we place a copy of that event into event in the entity's stream in the qa_sharedevents table. In addition, by default, we place a copy of that event into
the list of news updates for each user subscribed to the stream, via the qa_userevents table. the list of news updates for each user subscribed to the stream, via the qa_userevents table.
However, if there are more than a certain number of subscribers to the stream, we skip this second step, i.e. we However, if there are more than a certain number of subscribers to the stream, we skip this second step, i.e. we
only record one copy in the qa_sharedevents table. This limits the cost of publishing an event. only record one copy in the qa_sharedevents table. This limits the cost of publishing an event.
...@@ -73,10 +73,10 @@ ...@@ -73,10 +73,10 @@
Note that this approach isn't aimed at reducing the total cost of keeping all users up-to-date on all events, but Note that this approach isn't aimed at reducing the total cost of keeping all users up-to-date on all events, but
rather ensuring that no individual operation (posting an event or retrieving a user's list of updates) takes too rather ensuring that no individual operation (posting an event or retrieving a user's list of updates) takes too
long, since that would turn into a very slow response time for the corresponding HTTP request. long, since that would turn into a very slow response time for the corresponding HTTP request.
What should we use for the threshold T, so that if a stream has more than T subscribers, its events are only What should we use for the threshold T, so that if a stream has more than T subscribers, its events are only
recorded in the shared stream? One approach is as follows: recorded in the shared stream? One approach is as follows:
[this ignores stream length and truncation, which are constant factors] [this ignores stream length and truncation, which are constant factors]
T = our threshold T = our threshold
...@@ -102,7 +102,7 @@ ...@@ -102,7 +102,7 @@
number of (total) shared streams that any of those users are subscribed to. If this is above T, that means that our number of (total) shared streams that any of those users are subscribed to. If this is above T, that means that our
maximum cost of retrieving a list of news updates is starting to go past our maximum cost of recording an event. So maximum cost of retrieving a list of news updates is starting to go past our maximum cost of recording an event. So
we rebalance things out by increasing T as appropriate, for use in future cases. we rebalance things out by increasing T as appropriate, for use in future cases.
Note that once an event stream has made this switch, to be accessed only via its shared stream, we don't go back. Note that once an event stream has made this switch, to be accessed only via its shared stream, we don't go back.
*/ */
...@@ -117,59 +117,59 @@ ...@@ -117,59 +117,59 @@
$threshold=qa_opt('max_copy_user_updates'); // if this many users subscribe to it, create a shared stream $threshold=qa_opt('max_copy_user_updates'); // if this many users subscribe to it, create a shared stream
// Add in the favorite for this user, unshared events at first (will be switched later if appropriate) // Add in the favorite for this user, unshared events at first (will be switched later if appropriate)
qa_db_query_sub( qa_db_query_sub(
'INSERT IGNORE INTO ^userfavorites (userid, entitytype, entityid, nouserevents) VALUES ($, $, #, 0)', 'INSERT IGNORE INTO ^userfavorites (userid, entitytype, entityid, nouserevents) VALUES ($, $, #, 0)',
$userid, $entitytype, $entityid $userid, $entitytype, $entityid
); );
// See whether this entity already has another favoriter who uses its shared event stream // See whether this entity already has another favoriter who uses its shared event stream
$useshared=qa_db_read_one_value(qa_db_query_sub( $useshared=qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents>0 LIMIT 1', 'SELECT COUNT(*) FROM ^userfavorites WHERE entitytype=$ AND entityid=# AND nouserevents>0 LIMIT 1',
$entitytype, $entityid $entitytype, $entityid
)); ));
// If not, check whether it's time to switch it over to a shared stream // If not, check whether it's time to switch it over to a shared stream
if (!$useshared) { if (!$useshared) {
$favoriters=qa_db_read_one_value(qa_db_query_sub( $favoriters=qa_db_read_one_value(qa_db_query_sub(
'SELECT COUNT(*) FROM ^userfavorites WHERE entitytype=$ AND entityid=# LIMIT #', 'SELECT COUNT(*) FROM ^userfavorites WHERE entitytype=$ AND entityid=# LIMIT #',
$entitytype, $entityid, $threshold $entitytype, $entityid, $threshold
)); ));
$useshared=($favoriters >= $threshold); $useshared=($favoriters >= $threshold);
} }
// If we're going to use the shared stream... // If we're going to use the shared stream...
if ($useshared) { if ($useshared) {
// ... for all the people for whom we're switching this to a shared stream, find the highest number of other shared streams they have // ... for all the people for whom we're switching this to a shared stream, find the highest number of other shared streams they have
$maxshared=qa_db_read_one_value(qa_db_query_sub( $maxshared=qa_db_read_one_value(qa_db_query_sub(
'SELECT MAX(c) FROM (SELECT COUNT(*) AS c FROM ^userfavorites AS shared JOIN ^userfavorites AS unshared '. 'SELECT MAX(c) FROM (SELECT COUNT(*) AS c FROM ^userfavorites AS shared JOIN ^userfavorites AS unshared '.
'WHERE shared.userid=unshared.userid AND shared.nouserevents>0 AND unshared.entitytype=$ AND unshared.entityid=# AND unshared.nouserevents=0 GROUP BY shared.userid) y', 'WHERE shared.userid=unshared.userid AND shared.nouserevents>0 AND unshared.entitytype=$ AND unshared.entityid=# AND unshared.nouserevents=0 GROUP BY shared.userid) y',
$entitytype, $entityid $entitytype, $entityid
)); ));
// ... if this number is greater than our current 'max_copy_user_updates' threshold, increase that threshold (see long comment above) // ... if this number is greater than our current 'max_copy_user_updates' threshold, increase that threshold (see long comment above)
if (($maxshared+1)>$threshold) if (($maxshared+1)>$threshold)
qa_opt('max_copy_user_updates', $maxshared+1); qa_opt('max_copy_user_updates', $maxshared+1);
// ... now switch all unshared favoriters (including this new one) over to be shared // ... now switch all unshared favoriters (including this new one) over to be shared
qa_db_query_sub( qa_db_query_sub(
'UPDATE ^userfavorites SET nouserevents=1 WHERE entitytype=$ AND entityid=# AND nouserevents=0', 'UPDATE ^userfavorites SET nouserevents=1 WHERE entitytype=$ AND entityid=# AND nouserevents=0',
$entitytype, $entityid $entitytype, $entityid
); );
// Otherwise if we're going to record this in user-specific streams ... // Otherwise if we're going to record this in user-specific streams ...
} else { } else {
require_once QA_INCLUDE_DIR.'qa-db-events.php'; require_once QA_INCLUDE_DIR.'qa-db-events.php';
// ... copy across recent events from the shared stream // ... copy across recent events from the shared stream
qa_db_query_sub( qa_db_query_sub(
...@@ -178,14 +178,14 @@ ...@@ -178,14 +178,14 @@
'^sharedevents WHERE entitytype=$ AND entityid=#', '^sharedevents WHERE entitytype=$ AND entityid=#',
$userid, $entitytype, $entityid $userid, $entitytype, $entityid
); );
// ... and truncate the user's stream as appropriate // ... and truncate the user's stream as appropriate
qa_db_user_events_truncate($userid); qa_db_user_events_truncate($userid);
} }
} }
function qa_db_favorite_delete($userid, $entitytype, $entityid) function qa_db_favorite_delete($userid, $entitytype, $entityid)
/* /*
Delete the entity $entitytype with $entityid from the favorites list of $userid, removing any corresponding events Delete the entity $entitytype with $entityid from the favorites list of $userid, removing any corresponding events
...@@ -196,13 +196,13 @@ ...@@ -196,13 +196,13 @@
'DELETE FROM ^userfavorites WHERE userid=$ AND entitytype=$ AND entityid=#', 'DELETE FROM ^userfavorites WHERE userid=$ AND entitytype=$ AND entityid=#',
$userid, $entitytype, $entityid $userid, $entitytype, $entityid
); );
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^userevents WHERE userid=$ AND entitytype=$ AND entityid=#', 'DELETE FROM ^userevents WHERE userid=$ AND entitytype=$ AND entityid=#',
$userid, $entitytype, $entityid $userid, $entitytype, $entityid
); );
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-db-hotness.php File: qa-include/qa-db-hotness.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Functions for dealing with question hotness in the database Description: Functions for dealing with question hotness in the database
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
header('Location: ../'); header('Location: ../');
exit; exit;
} }
function qa_db_hotness_update($firstpostid, $lastpostid=null, $viewincrement=false) function qa_db_hotness_update($firstpostid, $lastpostid=null, $viewincrement=false)
/* /*
Recalculate the hotness in the database for posts $firstpostid to $lastpostid (if specified) Recalculate the hotness in the database for posts $firstpostid to $lastpostid (if specified)
...@@ -37,11 +37,11 @@ ...@@ -37,11 +37,11 @@
*/ */
{ {
if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); } if (qa_to_override(__FUNCTION__)) { $args=func_get_args(); return qa_call_override(__FUNCTION__, $args); }
if (qa_should_update_counts()) { if (qa_should_update_counts()) {
if (!isset($lastpostid)) if (!isset($lastpostid))
$lastpostid=$firstpostid; $lastpostid=$firstpostid;
$query= "UPDATE ^posts AS x, (SELECT parents.postid, parents.created AS qcreated, COALESCE(MAX(children.created), parents.created) as acreated, COUNT(children.postid) AS acount, parents.netvotes, parents.views FROM ^posts AS parents LEFT JOIN ^posts AS children ON parents.postid=children.parentid AND children.type='A' WHERE parents.postid>=# AND parents.postid<=# AND LEFT(parents.type, 1)='Q' GROUP BY postid) AS a SET x.hotness=(". $query= "UPDATE ^posts AS x, (SELECT parents.postid, parents.created AS qcreated, COALESCE(MAX(children.created), parents.created) as acreated, COUNT(children.postid) AS acount, parents.netvotes, parents.views FROM ^posts AS parents LEFT JOIN ^posts AS children ON parents.postid=children.parentid AND children.type='A' WHERE parents.postid>=# AND parents.postid<=# AND LEFT(parents.type, 1)='Q' GROUP BY postid) AS a SET x.hotness=(".
'((TO_DAYS(a.qcreated)-734138)*86400.0+TIME_TO_SEC(a.qcreated))*# + '. // zero-point is Jan 1, 2010 '((TO_DAYS(a.qcreated)-734138)*86400.0+TIME_TO_SEC(a.qcreated))*# + '. // zero-point is Jan 1, 2010
'((TO_DAYS(a.acreated)-734138)*86400.0+TIME_TO_SEC(a.acreated))*# + '. '((TO_DAYS(a.acreated)-734138)*86400.0+TIME_TO_SEC(a.acreated))*# + '.
...@@ -49,9 +49,9 @@ ...@@ -49,9 +49,9 @@
'(a.netvotes+0.0)*# + '. '(a.netvotes+0.0)*# + '.
'(a.views+0.0+#)*#'. '(a.views+0.0+#)*#'.
')'.($viewincrement ? ', x.views=x.views+1, x.lastviewip=INET_ATON($)' : '').' WHERE x.postid=a.postid'; ')'.($viewincrement ? ', x.views=x.views+1, x.lastviewip=INET_ATON($)' : '').' WHERE x.postid=a.postid';
// Additional multiples based on empirical analysis of activity on Q2A meta site to give approx equal influence for all factors // Additional multiples based on empirical analysis of activity on Q2A meta site to give approx equal influence for all factors
$arguments=array( $arguments=array(
$firstpostid, $firstpostid,
$lastpostid, $lastpostid,
...@@ -62,10 +62,10 @@ ...@@ -62,10 +62,10 @@
$viewincrement ? 1 : 0, $viewincrement ? 1 : 0,
qa_opt('hot_weight_views')*4000, qa_opt('hot_weight_views')*4000,
); );
if ($viewincrement) if ($viewincrement)
$arguments[]=qa_remote_ip_address(); $arguments[]=qa_remote_ip_address();
qa_db_query_raw(qa_db_apply_sub($query, $arguments)); qa_db_query_raw(qa_db_apply_sub($query, $arguments));
} }
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-db-limits.php File: qa-include/qa-db-limits.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Database-level access to tables which monitor rate limits Description: Database-level access to tables which monitor rate limits
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -38,28 +38,28 @@ ...@@ -38,28 +38,28 @@
{ {
$selects=array(); $selects=array();
$arguments=array(); $arguments=array();
if (isset($userid)) { if (isset($userid)) {
$selects[]="(SELECT 'user' AS limitkey, period, count FROM ^userlimits WHERE userid=$ AND action=$)"; $selects[]="(SELECT 'user' AS limitkey, period, count FROM ^userlimits WHERE userid=$ AND action=$)";
$arguments[]=$userid; $arguments[]=$userid;
$arguments[]=$action; $arguments[]=$action;
} }
if (isset($ip)) { if (isset($ip)) {
$selects[]="(SELECT 'ip' AS limitkey, period, count FROM ^iplimits WHERE ip=COALESCE(INET_ATON($), 0) AND action=$)"; $selects[]="(SELECT 'ip' AS limitkey, period, count FROM ^iplimits WHERE ip=COALESCE(INET_ATON($), 0) AND action=$)";
$arguments[]=$ip; $arguments[]=$ip;
$arguments[]=$action; $arguments[]=$action;
} }
if (count($selects)) { if (count($selects)) {
$query=qa_db_apply_sub(implode(' UNION ALL ', $selects), $arguments); $query=qa_db_apply_sub(implode(' UNION ALL ', $selects), $arguments);
return qa_db_read_all_assoc(qa_db_query_raw($query), 'limitkey'); return qa_db_read_all_assoc(qa_db_query_raw($query), 'limitkey');
} else } else
return array(); return array();
} }
function qa_db_limits_user_add($userid, $action, $period, $count) function qa_db_limits_user_add($userid, $action, $period, $count)
/* /*
Increment the database rate limit count for user $userid and $action by $count within $period Increment the database rate limit count for user $userid and $action by $count within $period
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
); );
} }
function qa_db_limits_ip_add($ip, $action, $period, $count) function qa_db_limits_ip_add($ip, $action, $period, $count)
/* /*
Increment the database rate limit count for IP address $ip and $action by $count within $period Increment the database rate limit count for IP address $ip and $action by $count within $period
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-db-maxima.php File: qa-include/qa-db-maxima.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Definitions that determine database column size and rows retrieved Description: Definitions that determine database column size and rows retrieved
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
@define('QA_DB_RETRIEVE_COMPLETE_TAGS', 1000); @define('QA_DB_RETRIEVE_COMPLETE_TAGS', 1000);
@define('QA_DB_RETRIEVE_MESSAGES', 20); @define('QA_DB_RETRIEVE_MESSAGES', 20);
// Keep event streams trimmed - not worth storing too many events per question because we only display the // Keep event streams trimmed - not worth storing too many events per question because we only display the
// most recent event for each question, that has not been invalidated due to hiding/unselection/etc... // most recent event for each question, that has not been invalidated due to hiding/unselection/etc...
......
<?php <?php
/* /*
Question2Answer (c) Gideon Greenspan Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-db-messages.php File: qa-include/qa-db-messages.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Database-level access to messages table for private message history Description: Database-level access to messages table for private message history
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -40,10 +40,10 @@ ...@@ -40,10 +40,10 @@
'INSERT INTO ^messages (type, fromuserid, touserid, content, format, created) VALUES ($, #, #, $, $, NOW())', 'INSERT INTO ^messages (type, fromuserid, touserid, content, format, created) VALUES ($, #, #, $, $, NOW())',
$public ? 'PUBLIC' : 'PRIVATE', $fromuserid, $touserid, $content, $format $public ? 'PUBLIC' : 'PRIVATE', $fromuserid, $touserid, $content, $format
); );
return qa_db_last_insert_id(); return qa_db_last_insert_id();
} }
function qa_db_message_delete($messageid) function qa_db_message_delete($messageid)
/* /*
......
<?php <?php
/* /*
Question2Answer (c) Gideon Greenspan Question2Answer (c) Gideon Greenspan
http://www.question2answer.org/ http://www.question2answer.org/
File: qa-include/qa-db-metas.php File: qa-include/qa-db-metas.php
Version: See define()s at top of qa-include/qa-base.php Version: See define()s at top of qa-include/qa-base.php
Description: Database-level access to metas tables Description: Database-level access to metas tables
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
qa_db_meta_set('usermetas', 'userid', $userid, $key, $value); qa_db_meta_set('usermetas', 'userid', $userid, $key, $value);
} }
function qa_db_usermeta_clear($userid, $key) function qa_db_usermeta_clear($userid, $key)
/* /*
Clear the metadata for user $userid with $key ($key can also be an array of keys) Clear the metadata for user $userid with $key ($key can also be an array of keys)
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
qa_db_meta_clear('usermetas', 'userid', $userid, $key); qa_db_meta_clear('usermetas', 'userid', $userid, $key);
} }
function qa_db_usermeta_get($userid, $key) function qa_db_usermeta_get($userid, $key)
/* /*
Return the metadata value for user $userid with $key ($key can also be an array of keys in which case this Return the metadata value for user $userid with $key ($key can also be an array of keys in which case this
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
{ {
return qa_db_meta_get('usermetas', 'userid', $userid, $key); return qa_db_meta_get('usermetas', 'userid', $userid, $key);
} }
function qa_db_postmeta_set($postid, $key, $value) function qa_db_postmeta_set($postid, $key, $value)
/* /*
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
qa_db_meta_set('postmetas', 'postid', $postid, $key, $value); qa_db_meta_set('postmetas', 'postid', $postid, $key, $value);
} }
function qa_db_postmeta_clear($postid, $key) function qa_db_postmeta_clear($postid, $key)
/* /*
Clear the metadata for post $postid with $key ($key can also be an array of keys) Clear the metadata for post $postid with $key ($key can also be an array of keys)
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
qa_db_meta_clear('postmetas', 'postid', $postid, $key); qa_db_meta_clear('postmetas', 'postid', $postid, $key);
} }
function qa_db_postmeta_get($postid, $key) function qa_db_postmeta_get($postid, $key)
/* /*
Return the metadata value for post $postid with $key ($key can also be an array of keys in which case this Return the metadata value for post $postid with $key ($key can also be an array of keys in which case this
...@@ -94,7 +94,7 @@ ...@@ -94,7 +94,7 @@
qa_db_meta_set('categorymetas', 'categoryid', $categoryid, $key, $value); qa_db_meta_set('categorymetas', 'categoryid', $categoryid, $key, $value);
} }
function qa_db_categorymeta_clear($categoryid, $key) function qa_db_categorymeta_clear($categoryid, $key)
/* /*
Clear the metadata for category $categoryid with $key ($key can also be an array of keys) Clear the metadata for category $categoryid with $key ($key can also be an array of keys)
...@@ -103,7 +103,7 @@ ...@@ -103,7 +103,7 @@
qa_db_meta_clear('categorymetas', 'categoryid', $categoryid, $key); qa_db_meta_clear('categorymetas', 'categoryid', $categoryid, $key);
} }
function qa_db_categorymeta_get($categoryid, $key) function qa_db_categorymeta_get($categoryid, $key)
/* /*
Return the metadata value for category $categoryid with $key ($key can also be an array of keys in which Return the metadata value for category $categoryid with $key ($key can also be an array of keys in which
...@@ -112,7 +112,7 @@ ...@@ -112,7 +112,7 @@
{ {
return qa_db_meta_get('categorymetas', 'categoryid', $categoryid, $key); return qa_db_meta_get('categorymetas', 'categoryid', $categoryid, $key);
} }
function qa_db_tagmeta_set($tag, $key, $value) function qa_db_tagmeta_set($tag, $key, $value)
/* /*
...@@ -122,7 +122,7 @@ ...@@ -122,7 +122,7 @@
qa_db_meta_set('tagmetas', 'tag', $tag, $key, $value); qa_db_meta_set('tagmetas', 'tag', $tag, $key, $value);
} }
function qa_db_tagmeta_clear($tag, $key) function qa_db_tagmeta_clear($tag, $key)
/* /*
Clear the metadata for tag $tag with $key ($key can also be an array of keys) Clear the metadata for tag $tag with $key ($key can also be an array of keys)
...@@ -131,7 +131,7 @@ ...@@ -131,7 +131,7 @@
qa_db_meta_clear('tagmetas', 'tag', $tag, $key); qa_db_meta_clear('tagmetas', 'tag', $tag, $key);
} }
function qa_db_tagmeta_get($tag, $key) function qa_db_tagmeta_get($tag, $key)
/* /*
Return the metadata value for tag $tag with $key ($key can also be an array of keys in which case this Return the metadata value for tag $tag with $key ($key can also be an array of keys in which case this
...@@ -142,7 +142,7 @@ ...@@ -142,7 +142,7 @@
} }
function qa_db_meta_set($metatable, $idcolumn, $idvalue, $title, $content) function qa_db_meta_set($metatable, $idcolumn, $idvalue, $title, $content)
/* /*
Internal general function to set metadata Internal general function to set metadata
*/ */
...@@ -153,7 +153,7 @@ ...@@ -153,7 +153,7 @@
); );
} }
function qa_db_meta_clear($metatable, $idcolumn, $idvalue, $title) function qa_db_meta_clear($metatable, $idcolumn, $idvalue, $title)
/* /*
Internal general function to clear metadata Internal general function to clear metadata
...@@ -165,7 +165,7 @@ ...@@ -165,7 +165,7 @@
'DELETE FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title IN ($)', 'DELETE FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title IN ($)',
$idvalue, $title $idvalue, $title
); );
} else } else
qa_db_query_sub( qa_db_query_sub(
'DELETE FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title=$', 'DELETE FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title=$',
...@@ -173,7 +173,7 @@ ...@@ -173,7 +173,7 @@
); );
} }
function qa_db_meta_get($metatable, $idcolumn, $idvalue, $title) function qa_db_meta_get($metatable, $idcolumn, $idvalue, $title)
/* /*
Internal general function to return metadata Internal general function to return metadata
...@@ -187,7 +187,7 @@ ...@@ -187,7 +187,7 @@
), 'title', 'content'); ), 'title', 'content');
else else
return array(); return array();
} else } else
return qa_db_read_one_value(qa_db_query_sub( return qa_db_read_one_value(qa_db_query_sub(
'SELECT content FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title=$', 'SELECT content FROM ^'.$metatable.' WHERE '.$idcolumn.'=$ AND title=$',
...@@ -195,7 +195,7 @@ ...@@ -195,7 +195,7 @@
), true); ), true);
} }
/* /*
Omit PHP closing tag to help avoid accidental output Omit PHP closing tag to help avoid accidental output
*/ */
\ No newline at end of file
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