1<?PHP 2/** 3 * StopForumSpam2 Plugin - Helper Section 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author HokkaidoPerson <dosankomali@yahoo.co.jp> 7 */ 8 9if(!defined('DOKU_INC')) die(); 10 11 12class helper_plugin_stopforumspam2 extends DokuWiki_Plugin { 13 14 /** 15 * Return the raw result of the investigation 16 * 17 * @param string or array $ip - Do nothing about the IP address if empty 18 * @param string or array $email - Do nothing about the e-mail address if empty 19 * @param string or array $username - Do nothing about the user name if empty 20 * @param string $wildcards - Specify the wildcards if necessary. Create the string of wildcards divided by "&". DO NOT specify serialised formatting wildcards such as 'serial', or the function will not run properly. e.g.: 'nobadusername' e.g.: 'nobadip&nobademail¬orexit' 21 * @return array - The array contains the whole data returned (converted from the json data to the array). See https://www.stopforumspam.com/usage 22 */ 23 function rawdata($ip = null, $email = null, $username = null, $wildcards = null){ 24 // All arguments are empty? Completely nothing to do. Return the empty array. 25 if ($ip == null and $email == null and $username == null) return array(); 26 27 // The script below was adopted from https://www.stopforumspam.com/usage 28 // setup the URL 29 $data = array( 30 'ip' => $ip, 31 'username' => $username, 32 'email' => $email, 33 ); 34 35 $data = http_build_query($data, '', '&', PHP_QUERY_RFC3986); 36 if ($wildcards != null) $data .= '&' . preg_replace('/[^a-z0-9&=]+/', '', $wildcards); 37 38 // init the request, set some info, send it and finally close it 39 $this->ch = curl_init(); 40 if ($this->ch) { 41 curl_setopt ($this->ch, CURLOPT_URL, 'http://api.stopforumspam.org/api?json'); 42 curl_setopt ($this->ch, CURLOPT_POST, 1); 43 curl_setopt ($this->ch, CURLOPT_POSTFIELDS, $data); 44 curl_setopt ($this->ch, CURLOPT_RETURNTRANSFER, true); 45 46 $result = curl_exec($this->ch); 47 curl_close($this->ch); 48 } 49 // End of adoption from https://www.stopforumspam.com/usage 50 return json_decode($result, true); 51 } 52 53 /** 54 * Look for the frequency score of given IP address, e-mail address, and(or) user name 55 * 56 * @param string $ip - Do nothing about the IP address if empty 57 * @param string $email - Do nothing about the e-mail address if empty 58 * @param string $username - Do nothing about the user name if empty 59 * @param boolean $returnvalue - If true, this function returns the frequency score itself. If false, it checks whether or not the score is as large as or higher than $border. This will be TRUE if one or more of the IP, e-mail, and user name is likely a spammer. 60 * @param value $border - The conf "freqBorder" will be used if empty or minus value. If $returnvalue is TRUE, the $border will be no use. Don't check if 0. 61 * @return boolean (if $returnvalue is false) or array (otherwise) - The boolean will be TRUE if the user is regarded as a spammer, or FALSE otherwise. The array's components will be values with keys "ip", "email", and "username". If the plugin fail to read the frequency, the value will be -1. 62 */ 63 function freqcheck($ip = null, $email = null, $username = null, $returnvalue = FALSE, $border = null){ 64 global $INFO; 65 66 // All arguments are empty? Completely nothing to do. Return FALSE. 67 if ($ip == null and $email == null and $username == null) return FALSE; 68 69 if ($border === null or $border < 0) $border = $this->getConf('freqBorder'); 70 if ($border == 0 and $returnvalue == FALSE) return FALSE; 71 if ($this->whitelists and $returnvalue == FALSE) return FALSE; 72 73 // Get the data from the function "rawdata" above. 74 $resultarray = $this->rawdata($ip, $email, $username); 75 76 if (isset($resultarray['ip']['frequency'])) $ipfreq = $resultarray['ip']['frequency']; else $ipfreq = -1; 77 if (isset($resultarray['email']['frequency'])) $emailfreq = $resultarray['email']['frequency']; else $emailfreq = -1; 78 if (isset($resultarray['username']['frequency'])) $namefreq = $resultarray['username']['frequency']; else $namefreq = -1; 79 if (isset($resultarray['ip']['confidence'])) $ipconf = $resultarray['ip']['confidence']; else $ipconf = -1; 80 if (isset($resultarray['email']['confidence'])) $emailconf = $resultarray['email']['confidence']; else $emailconf = -1; 81 if (isset($resultarray['username']['confidence'])) $nameconf = $resultarray['username']['confidence']; else $nameconf = -1; 82 83 if ($returnvalue) return array('ip' => $ipfreq, 'email' => $emailfreq, 'username' => $namefreq); 84 85 if ($ipfreq >= $border or $emailfreq >= $border or $namefreq >= $border) { 86 $logfilename = $this->getConf('logPlace'); 87 if ($logfilename == '') return TRUE; 88 if ($loghandle = fopen($logfilename, 'a')) { 89 $logcontent = "=== " . date('H:i:s M d, Y') . " - higher frequency score than the border ===\n"; 90 if ($ip != '') $logcontent .= "IP: " . $ip .", frequency " . $ipfreq . ", confidence " . $ipconf . "\n"; 91 if ($email != '') $logcontent .= "E-mail Address: " . $email .", frequency " . $emailfreq . ", confidence " . $emailconf . "\n"; 92 if ($username != '') $logcontent .= "User Name: " . $username .", frequency " . $namefreq . ", confidence " . $nameconf . "\n"; 93 $logcontent .= "It was accessing " . $INFO['id'] . "\n\n"; 94 fwrite($loghandle, $logcontent); 95 fclose($loghandle); 96 } 97 return TRUE; 98 } else return FALSE; 99 } 100 101 /** 102 * Look for the confidence score of given IP address, e-mail address, and(or) user name 103 * 104 * @param string $ip - Do nothing about the IP address if empty 105 * @param string $email - Do nothing about the e-mail address if empty 106 * @param string $username - Do nothing about the user name if empty 107 * @param boolean $returnvalue - If true, this function returns the confidence score itself. If false, it checks whether or not the score is as large as or higher than $border. This will be TRUE if one or more of the IP, e-mail, and user name is likely a spammer. 108 * @param value $border - The conf "confidenceBorder" will be used if empty or minus value. If $returnvalue is TRUE, the $border will be no use. Don't check if 0. 109 * @return boolean (if $returnvalue is false) or array (otherwise) - The boolean will be TRUE if the user is regarded as a spammer, or FALSE otherwise. The array's components will be values with keys "ip", "email", and "username". If the plugin fail to read the confidence score, the value will be -1. 110 */ 111 function confcheck($ip = null, $email = null, $username = null, $returnvalue = FALSE, $border = null){ 112 global $INFO; 113 114 // All arguments are empty? Completely nothing to do. Return FALSE. 115 if ($ip == null and $email == null and $username == null) return FALSE; 116 117 if ($border === null or $border < 0) $border = $this->getConf('confidenceBorder'); 118 if ($border == 0 and $returnvalue == FALSE) return FALSE; 119 if ($this->whitelists and $returnvalue == FALSE) return FALSE; 120 121 // Get the data from the function "rawdata" above. 122 $resultarray = $this->rawdata($ip, $email, $username); 123 124 if (isset($resultarray['ip']['confidence'])) $ipconf = $resultarray['ip']['confidence']; else $ipconf = -1; 125 if (isset($resultarray['email']['confidence'])) $emailconf = $resultarray['email']['confidence']; else $emailconf = -1; 126 if (isset($resultarray['username']['confidence'])) $nameconf = $resultarray['username']['confidence']; else $nameconf = -1; 127 if (isset($resultarray['ip']['frequency'])) $ipfreq = $resultarray['ip']['frequency']; else $ipfreq = -1; 128 if (isset($resultarray['email']['frequency'])) $emailfreq = $resultarray['email']['frequency']; else $emailfreq = -1; 129 if (isset($resultarray['username']['frequency'])) $namefreq = $resultarray['username']['frequency']; else $namefreq = -1; 130 131 if ($returnvalue) return array('ip' => $ipconf, 'email' => $emailconf, 'username' => $nameconf); 132 133 if ($ipconf >= $border or $emailconf >= $border or $nameconf >= $border) { 134 $logfilename = $this->getConf('logPlace'); 135 if ($logfilename == '') return TRUE; 136 if ($loghandle = fopen($logfilename, 'a')) { 137 $logcontent = "=== " . date('H:i:s M d, Y') . " - higher confidence score than the border ===\n"; 138 if ($ip != '') $logcontent .= "IP: " . $ip .", frequency " . $ipfreq . ", confidence " . $ipconf . "\n"; 139 if ($email != '') $logcontent .= "E-mail Address: " . $email .", frequency " . $emailfreq . ", confidence " . $emailconf . "\n"; 140 if ($username != '') $logcontent .= "User Name: " . $username .", frequency " . $namefreq . ", confidence " . $nameconf . "\n"; 141 $logcontent .= "It was accessing " . $INFO['id'] . "\n\n"; 142 fwrite($loghandle, $logcontent); 143 fclose($loghandle); 144 } 145 return TRUE; 146 } else return FALSE; 147 } 148 149 /** 150 * Quick check of the IP address 151 * Investigates about both the frequency score and the confidence score. 152 * 153 * @param string $ip - Remote IP address will be used if empty 154 * @param value $freqborder - The conf "freqBorder" will be used if empty or minus value. Don't check if 0. 155 * @param value $confborder - The conf "confidenceBorder" will be used if empty or minus value. Don't check if 0. 156 * @return boolean - TRUE if the function freqcheck, confcheck, or both is(are) TRUE, FALSE otherwise. 157 */ 158 function quickipcheck($ip = null, $freqborder = null, $confborder = null){ 159 if ($ip == '') $ip = $_SERVER['REMOTE_ADDR']; 160 $freqcheck = FALSE; 161 $confcheck = FALSE; 162 163 $freqcheck = $this->freqcheck($ip, null, null, FALSE, $freqborder); 164 $confcheck = $this->confcheck($ip, null, null, FALSE, $confborder); 165 if ($freqcheck or $confcheck) return TRUE; else return FALSE; 166 } 167 168 /** 169 * Report and add a spammer to the database of the forum 170 * The API key in configuration "reportAPI" will be automatically used. 171 * 172 * @param string $ip - Required 173 * @param string $email - Required 174 * @param string $username - Required 175 * @param string $evidence - Optional 176 * @return array ('succeeded' => [TRUE if succeeded, or FALSE if failed], 'message' => [a message that indicates whether or not the plugin successfully reported the user (If failed, it contains the error message (sometimes sent by the API).)]) 177 */ 178 function addToDatabase($ip = null, $email = null, $username = null, $evidence = null){ 179 if ($ip == null or $email == null or $username == null) return array('succeeded' => FALSE, 'message' => $this->getLang('lackingArgs')); 180 $api = $this->getConf('reportAPI'); 181 if ($api == '') return array('succeeded' => FALSE, 'message' => $this->getLang('lackingAPI')); 182 183 // The script below was adopted from https://www.stopforumspam.com/usage 184 $data = array( 185 'username' => $username, 186 'ip_addr' => $ip, 187 'evidence' => $evidence, 188 'email' => $email, 189 'api_key' => $api 190 ); 191 192 $data = http_build_query($data, '', '&', PHP_QUERY_RFC3986); 193 194 $this->ch = curl_init(); 195 if ($this->ch) { 196 curl_setopt ($this->ch, CURLOPT_URL, 'https://www.stopforumspam.com/add.php'); 197 curl_setopt ($this->ch, CURLOPT_POST, 1); 198 curl_setopt ($this->ch, CURLOPT_POSTFIELDS, $data); 199 curl_setopt ($this->ch, CURLOPT_RETURNTRANSFER, true); 200 $result = curl_exec ($this->ch); 201 $detail = curl_getinfo($this->ch); 202 curl_close ($this->ch); 203 204 if ($detail['http_code'] == '200') return array('succeeded' => TRUE, 'message' => $this->getLang('submitted')); else return array('succeeded' => FALSE, 'message' => $this->getLang('errorHappened') . strip_tags($result)); 205 206 } else return array('succeeded' => FALSE, 'message' => $this->getLang('curlError')); 207 } 208 209 /** 210 * Check about whitelists in the configuration 211 * 212 * @param string $ip 213 * @param string $email 214 * @param string $username 215 * @return boolean - TRUE if he is in the whitelist(s), FALSE otherwise 216 */ 217 function whitelists ($ip = null, $email = null, $username = null) { 218 global $INFO; 219 220 // IPs 221 $exlist = str_replace(array("\r\n", "\r", "\n"), "\n", $this->getConf('ipWhitelist')); 222 $exlist = preg_quote($exlist, '/'); 223 $exlist = str_replace('\*', '[0-9]+', $exlist); 224 $exlist = str_replace('\?', '[0-9]', $exlist); 225 $exlist = explode("\n", $exlist); 226 227 foreach ($exlist as $checking) { 228 if ($checking == '') continue; 229 $prefix = '/^' . $checking . '$/'; 230 if (preg_match($prefix, $ip)) return TRUE; 231 } 232 233 // User names 234 $exlist = str_replace(array("\r\n", "\r", "\n"), "\n", $this->getConf('nameWhitelist')); 235 $exlist = preg_quote($exlist, '/'); 236 $exlist = str_replace('\*', '.+', $exlist); 237 $exlist = str_replace('\?', '.', $exlist); 238 $exlist = str_replace('~', '[0-9]+', $exlist); 239 $exlist = str_replace('\!', '[0-9]', $exlist); 240 $exlist = explode("\n", $exlist); 241 242 foreach ($exlist as $checking) { 243 if ($checking == '') continue; 244 $prefix = '/^' . $checking . '$/'; 245 if (preg_match($prefix, $username)) return TRUE; 246 } 247 248 // E-mail addresses 249 $exlist = str_replace(array("\r\n", "\r", "\n"), "\n", $this->getConf('emailWhitelist')); 250 $exlist = preg_quote($exlist, '/'); 251 $exlist = str_replace('\*', '.+', $exlist); 252 $exlist = str_replace('\?', '.', $exlist); 253 $exlist = str_replace('~', '[0-9]+', $exlist); 254 $exlist = str_replace('\!', '[0-9]', $exlist); 255 $exlist = explode("\n", $exlist); 256 257 // IDN conversion 258 $emexp = explode('@', $email, 2); 259 $ascii = idn_to_ascii($emexp[1]); 260 $utf8 = idn_to_utf8($emexp[1]); 261 $ascii = $emexp[0] . $ascii; 262 $utf8 = $emexp[0] . $utf8; 263 264 foreach ($exlist as $checking) { 265 if ($checking == '') continue; 266 $prefix = '/^' . $checking . '$/'; 267 if (preg_match($prefix, $ascii)) return TRUE; 268 if (preg_match($prefix, $utf8)) return TRUE; 269 } 270 271 // Skip logged-in users, managers and superusers? 272 if ($this->getConf('skipMgAndSp') == 'mg' && auth_ismanager()) return TRUE; 273 if ($this->getConf('skipMgAndSp') == 'sp' && auth_isadmin()) return TRUE; 274 if ($this->getConf('skipMgAndSp') == 'user' && $_SERVER['REMOTE_USER']) return TRUE; 275 276 // Check about a list of users and user groups 277 if(auth_isMember($this->getConf('userWhitelist'), $_SERVER['REMOTE_USER'], (array) $USERINFO['grps'])) return TRUE; 278 279 // Not in whitelists 280 return FALSE; 281 } 282} 283