Re: Improving User Notes In The Manual -- First Steps
| From: | Sherif Ramadan | Date: | Sun, 09 Sep 2012 17:34:51 +0000 |
| Subject: | Re: Improving User Notes In The Manual -- First Steps | ||
| References: | 1 2 3 4 5 | Groups: | php.doc php.webmaster |
| Request: | Send a blank email to php-webmaster+get-14669@lists.php.net to get a copy of this message | ||
From 362719eb0aaefb323e05a15ddcd2077e84b18fee Mon Sep 17 00:00:00 2001
From: Sherif Ramadan <googleguy@php.net>
Date: Sun, 9 Sep 2012 13:31:36 -0400
Subject: [PATCH] Updated backend scripts for user notes voting/flagging.
---
entry/user-notes-flag.php | 160 +++++++++++++++++++++++++++++++++++++++++++++
entry/user-notes-vote.php | 105 +++++++++++++++++++++++++++++
fetch/user-notes.php | 13 +++-
3 files changed, 275 insertions(+), 3 deletions(-)
create mode 100644 entry/user-notes-flag.php
create mode 100644 entry/user-notes-vote.php
diff --git a/entry/user-notes-flag.php b/entry/user-notes-flag.php
new file mode 100644
index 0000000..84eac24
--- /dev/null
+++ b/entry/user-notes-flag.php
@@ -0,0 +1,160 @@
+<?php
+/*
+ This script acts as the backend communication API for the user
notes flag feature.
+ Requests come in here from the mirrors to update the database with new flags.
+ master.php.net should respond with either an empty HTTP response
body or a non empty body -- currently "1" -- on
+ success/failure repsectively. An email is then sent out to
php-notes@lists.php.net to notify moderators.
+*/
+
+
+// Check database for IP limits and note id
+function db_check() {
+ $mailto = 'php-notes@lists.php.net';
+ $failto = 'googleguy@php.net'; // add other failto emails here as needed.
+
+ $db = "phpmasterdb";
+ $username = "nobody";
+ $password = "";
+ $host = "localhost";
+
+ if (!($dbh = @mysql_connect($host, $username, $password))) {
+ return false;
+ }
+
+ if (!(@mysql_select_db($db, $dbh))) {
+ return false;
+ }
+
+ $ip = $_POST['ip'];
+ if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 |
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
+ $ip = mysql_real_escape_string(sprintf("%u",ip2long($ip)));
+ }
+ elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 |
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
+ $ip = '0';
+ }
+ else {
+ $ip = '0';
+ }
+ $hostip =
mysql_real_escape_string(sprintf("%u",ip2long($_SERVER['REMOTE_ADDR'])));
+ $id = mysql_real_escape_string($_POST['noteid']);
+ // Check that the note id exists
+ $note_query = "SELECT COUNT(*) AS num, id, sect FROM note WHERE id = '$id'";
+ // Limit 1 flag per note, per client ip, per day
+ $client_query = "SELECT COUNT(*) AS num FROM flags WHERE ip = '$ip'
AND ts >= (NOW() - INTERVAL 1 DAY) AND note_id = '$id'";
+ // Limit 5 flag per note, per host ip, per minute
+ $host_query = "SELECT COUNT(*) AS num FROM flags WHERE hostip =
'$hostip' AND ts >= (NOW() - INTERVAL 1 MINUTE) AND note_id = '$id'";
+
+ if (!($result_note = @mysql_query($note_query))) {
+ return false;
+ }
+ $rows_note = @mysql_fetch_assoc($result_note);
+ if (empty($rows_note) || $rows_note['num'] == 0 ||
$rows_note['sect'] !== $_POST['sect']) {
+ return false;
+ }
+ $sect = $rows_note['sect'];
+ $note_id = $rows_note['id'];
+
+
+ if (!($result_client = @mysql_query($client_query))) {
+ return false;
+ }
+ $rows_client = @mysql_fetch_assoc($result_client);
+ if (empty($rows_client) || $rows_client['num'] >= 1) {
+ return false;
+ }
+
+ if (!($result_host = @mysql_query($host_query))) {
+ return false;
+ }
+ $rows_host = @mysql_fetch_assoc($result_host);
+ if (empty($rows_host) || $rows_host['num'] >= 5) {
+ return false;
+ }
+
+ $flag = mysql_real_escape_string($_POST['flag']);
+ $email = mysql_real_escape_string($_POST['email']);
+ $info = mysql_real_escape_string($_POST['info']);
+ $ts = mysql_real_escape_string(date("Y-m-d H:i:s"));
+ $insert_query = "INSERT INTO
flags(note_id,ip,hostip,ts,flag,email,info)
VALUES('$id','$ip','$hostip','$ts','$flag','$email','$info')";
+ if (!($result = @mysql_query($insert_query))) {
+ mail ($failto,
+ 'failed manual note flag query',
+ "Query failed: $insert_query\nError: ".mysql_error(),
+ 'From: php-webmaster@lists.php.net',
+ '-fnoreply@php.net'
+ );
+ return false;
+ }
+
+ $flag_id = mysql_insert_id();
+ if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
+ $user = filter_var($_POST['email'], FILTER_SANITIZE_STRIPPED,
FILTER_FLAG_STRIP_HIGH);
+ $user = str_replace(array("\r", "\n"), "", $user);
+ }
+ else {
+ $user = $_POST['email'];
+ }
+ $msg = <<<EMAIL_MSG
+A user has flagged a note! Please review it and take any necessary action.
+
+--------------------------------
+Note ID: $note_id
+Flag ID: $flag_id
+Section: $sect
+Email: $user
+Client IP: {$_POST['ip']}
+Host IP: {$_SERVER['REMOTE_ADDR']}
+Reason: {$_POST['flag']}
+Comment: {$_POST['info']}
+--------------------------------
+EMAIL_MSG;
+ mail($mailto,"note $note_id flagged in section '$sect'",$msg,"From:
$user\r\nMessage-ID: <note-$note_id@php.net>", "-fnoreply@php.net");
+
+ return true;
+}
+
+// Send email for flagged note
+function email_flag() {
+ return true;
+}
+
+// Initialize Global vars
+$flags = array(
+ "Spam",
+ "Offensive or abusive language",
+ "This should be a bug report",
+ "Note on wrong/unrelated page",
+ "Invalid or harmful code",
+ "Duplicate note",
+ "This is my note and I want it deleted",
+ "Other",
+);
+
+// Validate the request
+if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
+ header("HTTP/1.0 400", true);
+ exit();
+}
+if (empty($_POST['noteid']) || empty($_POST['sect']) ||
empty($_POST['flag']) || !isset($_POST['email']) ||
+ !isset($_POST['info']) || !isset($_POST['ip'])) {
+ header("HTTP/1.0 400", true);
+ exit();
+}
+if (!in_array($_POST['flag'],$flags, true)) {
+ header("HTTP/1.0 400", true);
+ exit();
+}
+
+// Check master DB for hostip and clientip limits
+if (!db_check()) {
+ header("HTTP/1.0 400", true);
+ exit();
+}
+
+if (!email_flag()) {
+ header("HTTP/1.0 400", true);
+ exit();
+}
+
+header("HTTP/1.0 200",true);
+echo 1;
diff --git a/entry/user-notes-vote.php b/entry/user-notes-vote.php
new file mode 100644
index 0000000..dc6c58b
--- /dev/null
+++ b/entry/user-notes-vote.php
@@ -0,0 +1,105 @@
+<?php
+/*
+ This script acts as the backend communication API for the user
notes vote feature.
+ Requests come in here from the mirrors to update the database with new votes.
+ master.php.net should respond with either a 400 HTTP status code
and empty body or 200 HTTP status with new updated
+ vote count in the body. This will let the mirror know whether the
request succeeded or failed.
+*/
+
+
+// Check database for IP limits
+function db_check() {
+ $db = "phpmasterdb";
+ $username = "nobody";
+ $password = "";
+ $host = "localhost";
+
+ if (!($dbh = @mysql_connect($host, $username, $password))) {
+ return false;
+ }
+
+ if (!(@mysql_select_db($db, $dbh))) {
+ return false;
+ }
+
+ $ip = mysql_real_escape_string(sprintf("%u",ip2long($_POST['ip'])));
+ $hostip =
mysql_real_escape_string(sprintf("%u",ip2long($_SERVER['REMOTE_ADDR'])));
+ $id = mysql_real_escape_string($_POST['noteid']);
+ // Check that the note id exists
+ $note_query = "SELECT COUNT(*) AS num, sect FROM note WHERE id = '$id'";
+ // Limit 1 vote per note, per client ip, per day
+ $client_query = "SELECT COUNT(*) AS num FROM votes WHERE ip = '$ip'
AND ts >= (NOW() - INTERVAL 1 DAY) AND note_id = '$id'";
+ // Limit 5 votes per note, per host ip, per minute
+ $host_query = "SELECT COUNT(*) AS num FROM votes WHERE hostip =
'$hostip' AND ts >= (NOW() - INTERVAL 1 MINUTE) AND note_id = '$id'";
+
+ if (!($result_note = @mysql_query($note_query))) {
+ return false;
+ }
+ $rows_note = @mysql_fetch_assoc($result_note);
+ if (empty($rows_note) || $rows_note['num'] == 0) {
+ return false;
+ }
+ // Check that the note is in the right section
+ if ($rows_note['sect'] !== $_POST['sect']) {
+ return false;
+ }
+
+ if (!($result_client = @mysql_query($client_query))) {
+ return false;
+ }
+ $rows_client = @mysql_fetch_assoc($result_client);
+ if (empty($rows_client) || $rows_client['num'] >= 100) {
+ return false;
+ }
+
+ if (!($result_host = @mysql_query($host_query))) {
+ return false;
+ }
+ $rows_host = @mysql_fetch_assoc($result_host);
+ if (empty($rows_host) || $rows_host['num'] >= 5) {
+ return false;
+ }
+
+ if ($_POST['vote'] === 'up') {
+ $vote = 1;
+ }
+ else {
+ $vote = 0;
+ }
+ $ts = mysql_real_escape_string(date("Y-m-d H:i:s"));
+ $insert_query = "INSERT INTO votes(note_id,ip,hostip,ts,vote)
VALUES('$id','$ip','$hostip','$ts','$vote')";
+ if (!($result = @mysql_query($insert_query))) {
+ return false;
+ }
+
+ if (!($getvotes = @mysql_query("SELECT SUM(votes.vote) AS up,
(COUNT(votes.vote) - SUM(votes.vote)) AS down FROM votes WHERE
votes.note_id = {$id}"))) {
+ return false;
+ }
+ $votes = mysql_fetch_assoc($getvotes);
+
+ return $votes['up'] - $votes['down'];
+}
+
+// Validate the request
+if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
+ header("HTTP/1.0 400", true);
+ exit();
+}
+if (empty($_POST['noteid']) || empty($_POST['sect']) ||
empty($_POST['vote']) || !isset($_POST['ip'])) {
+ header("HTTP/1.0 400", true);
+ exit();
+}
+if ($_POST['vote'] !== 'up' && $_POST['vote'] !==
'down') {
+ header("HTTP/1.0 400", true);
+ exit();
+}
+
+// Check master DB for hostip and clientip limits and other validations
+if (($vote_update = db_check()) === false) {
+ header("HTTP/1.0 400", true);
+ exit();
+}
+
+// If everything passes the response should be the new updated vote
count with HTTP 200 OK status code
+header("HTTP/1.0 200",true);
+echo $vote_update;
diff --git a/fetch/user-notes.php b/fetch/user-notes.php
index e941cfe..5169e6d 100644
--- a/fetch/user-notes.php
+++ b/fetch/user-notes.php
@@ -1,7 +1,7 @@
<?php
# token required, since this should only get accessed from rsync.php.net
-if (!isset($_REQUEST['token']) || md5($_REQUEST['token']) !=
"19a3ec370affe2d899755f005e5cd90e")
+if (!isset($token) || md5($token) != "19a3ec370affe2d899755f005e5cd90e")
die("token not correct.");
@mysql_connect("localhost","nobody","")
@@ -31,6 +31,13 @@ while ($row = mysql_fetch_array($res, MYSQL_ASSOC)) {
} else {
$user = '';
}
- echo "$row[id]|$row[sect]|$row[rate]|$row[ts]|$user|",
- base64_encode(gzcompress($row['note'],3)),"\n";
+ // We'll need to gather an array for the votes separately here
+ // @TODO: Find a better way to do this later
+ $getvotes = mysql_query("SELECT SUM(votes.vote) AS up,
(COUNT(votes.vote) - SUM(votes.vote)) AS down FROM votes WHERE
votes.note_id = {$row['id']}");
+ $votes = mysql_fetch_assoc($getvotes);
+ if (empty($votes['up'])) $votes['up'] = 0;
+ if (empty($votes['down'])) $votes['down'] = 0;
+ // Output here
+ echo
"{$row['id']}|{$row['sect']}|{$row['rate']}|{$row['ts']}|{$row['user']}|",
+
base64_encode(gzcompress($row['note'],3)),"|{$votes['up']}|{$votes['down']}\n";
}
--
1.7.5.4