xref: /web-master/entry/user-note.php (revision 3f5dc40d)
1<?php
2
3// service closed until we can filter spam
4//die ('[CLOSED]');
5
6include_once 'note-reasons.inc';
7include_once 'spam-lib.inc';
8include_once 'functions.inc';
9
10$mailto = 'php-notes@lists.php.net';
11$failto = 'jimw@php.net, alindeman@php.net, danbrown@php.net';
12
13function validateUser($user) {
14    $ret     = filter_var($user,    FILTER_VALIDATE_EMAIL);
15
16    // If its not a valid email then strip all tags and \r & \n (since this will be used in the mail "from" header) /
17    if(!$ret) {
18        $ret = filter_var($user,    FILTER_SANITIZE_STRIPPED, FILTER_FLAG_STRIP_HIGH);
19        $ret = str_replace(["\r", "\n"], "", $ret);
20    }
21    return trim($ret);
22}
23
24
25$user    = filter_input(INPUT_POST, "user",     FILTER_CALLBACK,            ["filter" => FILTER_CALLBACK, "options" => "validateUser"]);
26$note    = filter_input(INPUT_POST, "note",     FILTER_UNSAFE_RAW);
27$sect    = filter_input(INPUT_POST, "sect",     FILTER_SANITIZE_STRIPPED,   FILTER_FLAG_STRIP_HIGH);
28$ip      = filter_input(INPUT_POST, "ip",       FILTER_VALIDATE_IP,         FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE);
29$redirip = filter_input(INPUT_POST, "redirip",  FILTER_VALIDATE_IP,         FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE);
30
31if (empty($user) || empty($note) || empty($sect) || !$ip)
32  die("missing some parameters.");
33
34
35/* SPAM Checks ******************************************/
36$note_lc = strtolower($note);
37
38// Disallow URL SPAM
39if (check_spam_urls($note_lc, 4)) {
40    die ('[SPAM WORD]');
41}
42
43// Compare the text against a known list of bad words
44if (check_spam_words($note_lc, $words_blacklist)) {
45    die('[SPAM WORD]');
46}
47
48// Check if the IP is blacklisted
49if (($spamip=is_spam_ip($_SERVER['REMOTE_ADDR'])) || ($spamip=is_spam_ip($ip)) || ($redirip && $spamip=is_spam_ip($redirip))) {
50    die ("[SPAMMER] $spamip");
51}
52
53unset($note_lc);
54/* End SPAM Checks ******************************************/
55
56db_connect();
57
58/*
59After a discussion in #php about the
60vulnerability of the user notes system,
61I decided to implement a bit of hack
62prevention.  This makes sure that only
633 notes can be submitted per minute, which
64is very reasonable considering the current
65flow of notes usually submitted.  This prevents
66a large flood of notes from coming in.
67*/
68$query = 'SELECT COUNT(*) FROM note WHERE ts >= (NOW() - INTERVAL 1 MINUTE)';
69$result = db_query_safe($query);
70
71if (!$result) {
72  mail ($failto,
73       'failed manual note query',
74       "Query Failed: $query\nError: ".mysql_error(),
75       'From: php-webmaster@lists.php.net',
76	   '-fnoreply@php.net'
77  );
78  die("failed to query note db");
79}
80
81list ($count) = mysql_fetch_row ($result);
82
83if ($count >= 3) {
84  //Send error to myself.  If this happens too many times, I'll increase
85  //the amount of allowed notes
86  mail ('alindeman@php.net,didou@php.net,danbrown@php.net',
87	'[php-notes] Quota exceeded',
88	'Too many notes submitted in one minute.  Consider increasing quota' . "\n" .
89        'Occured at '.date ('M d, Y g:i:s A') . "\n" .
90	"User   : $user\n" .
91	"Section: $sect\n" .
92	"Note   : $note",
93	'From: php-webmaster@lists.php.net',
94	'-fnoreply@php.net'
95  );
96  die ('[TOO MANY NOTES]');
97}
98
99$sect = trim(preg_replace('/\.php$/','',$sect));
100
101//na = not approved.  Don't display notes until they are approved by an editor
102//This has been reverted until it has been discussed further.
103
104$query = "INSERT INTO note (user, note, sect, ts, status) VALUES (?, ?, ?,NOW(), NULL)";
105if (db_query_safe($query, [$user, $note, $sect])) {
106  $new_id = mysql_insert_id();
107  $msg = $note;
108
109  $msg .= "\n----\n";
110  $msg .= "Server IP: {$_SERVER['REMOTE_ADDR']}";
111  if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) || isset($_SERVER['HTTP_VIA'])) {
112    $msg .= " (proxied:";
113    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
114      $msg .= " " . hsc($_SERVER['HTTP_X_FORWARDED_FOR']);
115    }
116    if (isset($_SERVER['HTTP_VIA'])) {
117      $msg .= " " . hsc($_SERVER['HTTP_VIA']);
118    }
119    $msg .= ")";
120  }
121  $msg .= "\nProbable Submitter: {$ip}" . ($redirip ? ' (proxied: '.htmlspecialchars($redirip).')' : '');
122
123  $msg .= "\n----\n";
124//  $msg .= $spam_data;
125//  $msg .= "\n----\n";
126
127  $msg .= "Manual Page -- http://php.net/manual/en/$sect.php\n";
128  $msg .= "Edit        -- https://master.php.net/note/edit/$new_id\n";
129  //$msg .= "Approve     -- https://master.php.net/manage/user-notes.php?action=approve+$new_id&report=yes\n";
130  foreach ($note_del_reasons AS $reason) {
131    $msg .= "Del: "
132      . str_pad($reason, $note_del_reasons_pad)
133      . "-- https://master.php.net/note/delete/$new_id/" . urlencode($reason) ."\n";
134  }
135
136  // @phan-suppress-next-line PhanParamSuspiciousOrder - weird global padding count, but ok
137  $msg .= str_pad('Del: other reasons', $note_del_reasons_pad) . "-- https://master.php.net/note/delete/$new_id\n";
138  $msg .= "Reject      -- https://master.php.net/note/reject/$new_id\n";
139  $msg .= "Search      -- https://master.php.net/manage/user-notes.php\n";
140  # make sure we have a return address.
141  if (!$user) $user = "php-general@lists.php.net";
142  # strip spaces in email address, or will get a bad To: field
143  $user = str_replace(' ','',$user);
144  mail($mailto,"note $new_id added to $sect",$msg,"From: $user\r\nMessage-ID: <note-$new_id@php.net>", "-fnoreply@php.net");
145} else {
146  // mail it.
147  mail($failto,
148      'failed manual note query',
149      "Query Failed: $query\nError: ".mysql_error(),
150      'From: php-webmaster@lists.php.net',
151	  "-fnoreply@php.net");
152  die("failed to insert record");
153}
154
155
156
157
158
159//var_dump(is_spammer('127.0.0.1')); // false
160//var_dump(is_spammer('127.0.0.2')); // true
161
162?>
163