Simple Groupware PHP Cross Reference Groupware Applications

Source: /src/lib/pmwiki/scripts/blocklist.php - 234 lines - 9610 bytes - Summary - Text - Print

   1  <?php if (!defined('PmWiki')) exit();
   2  /*  Copyright 2006-2007 Patrick R. Michaud (pmichaud@pobox.com)
   3      This file is part of PmWiki; you can redistribute it and/or modify
   4      it under the terms of the GNU General Public License as published
   5      by the Free Software Foundation; either version 2 of the License, or
   6      (at your option) any later version.  See pmwiki.php for full details.
   7  
   8      This script adds blocklisting capabilities to PmWiki, and can
   9      be enabled by simply setting the following in local/config.php:
  10  
  11          $EnableBlocklist = 1;
  12  
  13      With $EnableBlocklist set to 1, this module will search through
  14      the SiteAdmin.Blocklist page, as well as any other pages given by
  15      the $Blocklist pages variable, looking for lines of the
  16      form "block:some phrase" or "block:/regex/", with "some phrase" 
  17      and "/regex/" indicating things to be excluded from any 
  18      posting to the site.  
  19  
  20      In addition, if a page contains IP addresses of the form
  21      "a.b.c.d" or "a.b.c.*", then any posts coming from hosts
  22      matching the address will be blocked.
  23  
  24      There is also an "unblock:..." form, which removes an entry
  25      from the blocklist.  This is useful for removing specific
  26      block items in wikifarms and with automatically downloaded
  27      blocklists (below).
  28  
  29      The script also has the capability of automatically downloading
  30      blocklists from other sources, such as chongqed.org and
  31      and the MoinMaster blocklist.  These are configured using
  32      the $BlocklistDownload array.  An $EnableBlocklist value
  33      of at least 10 configures PmWiki to automatically download
  34      these external blocklists and refresh them daily.
  35  
  36      More information about blocklists is available in the
  37      PmWiki.Blocklist page.
  38  */
  39  
  40  ##   Some recipes do page updates outside of the built-in posting
  41  ##   cycle, so $EnableBlocklistImmediate is used to determine if
  42  ##   we need to catch these.  Currently this defaults to enabled,
  43  ##   but at some point we may change the default to disabled.
  44  if (IsEnabled($EnableBlocklistImmediate, 1)) {
  45    SDVA($BlocklistActions, array('comment' => 1));
  46    if (isset($_POST['text']) && @$BlocklistActions[$action]) {
  47      Blocklist($pagename, $_POST['text']);
  48      if (!$EnablePost) {
  49        unset($_POST['post']);
  50        unset($_POST['postattr']);
  51        unset($_POST['postedit']);
  52      }
  53    }
  54  }
  55  
  56  ##   If $EnableBlocklist is set to 10 or higher, then arrange to 
  57  ##   periodically download the "chongqed" and "moinmaster" blacklists.
  58  if ($EnableBlocklist >= 10) {
  59    SDVA($BlocklistDownload['SiteAdmin.Blocklist-Chongqed'], array(
  60      'url' => 'http://blacklist.chongqed.org/',
  61      'format' => 'regex'));
  62    SDVA($BlocklistDownload['SiteAdmin.Blocklist-MoinMaster'], array(
  63      'url' => 'http://moinmaster.wikiwikiweb.de/BadContent?action=raw',
  64      'format' => 'regex'));
  65  }
  66  
  67  ##   CheckBlocklist is inserted into $EditFunctions, to automatically
  68  ##   check for blocks on anything being posted through the normal
  69  ##   "update a page cycle"
  70  array_unshift($EditFunctions, 'CheckBlocklist');
  71  function CheckBlocklist($pagename, &$page, &$new) { 
  72    StopWatch("CheckBlocklist: begin $pagename");
  73    $ptext = implode('', @$_POST);
  74    if (@$ptext) Blocklist($pagename, $ptext); 
  75    StopWatch("CheckBlocklist: end $pagename");
  76  }
  77  
  78  ##   Blocklist is the function that does all of the work of
  79  ##   checking for reasons to block a posting.  It reads
  80  ##   the available blocklist pages ($BlocklistPages) and
  81  ##   builds an array of strings and regular expressiongs to
  82  ##   be checked against the page; if any are found, then
  83  ##   posting is blocked (via $EnablePost=0).  The function
  84  ##   also checks the REMOTE_ADDR against any blocked IP addresses.
  85  function Blocklist($pagename, $text) {
  86    global $BlocklistPages, $BlockedMessagesFmt, $BlocklistDownload,
  87      $BlocklistDownloadRefresh, $Now, $EnablePost, $WhyBlockedFmt,
  88      $MessagesFmt, $BlocklistMessageFmt, $EnableWhyBlocked, $IsBlocked;
  89  
  90    StopWatch("Blocklist: begin $pagename");
  91  
  92    $BlocklistDownload = (array)@$BlocklistDownload;
  93    SDV($BlocklistPages, 
  94      array_merge(array('$SiteAdminGroup.Blocklist', 
  95                        '$SiteAdminGroup.Blocklist-Farm'),
  96                  array_keys($BlocklistDownload)));
  97    SDV($BlocklistMessageFmt, "<h3 class='wikimessage'>$[This post has been blocked by the administrator]</h3>");
  98    SDVA($BlockedMessagesFmt, array(
  99      'ip' => '$[Address blocked from posting]: ',
 100      'text' => '$[Text blocked from posting]: '));
 101    SDV($BlocklistDownloadRefresh, 86400);
 102  
 103    ##  Loop over all blocklist pages
 104    foreach((array)$BlocklistPages as $b) {
 105  
 106      ##  load the current blocklist page
 107      $pn = FmtPageName($b, $pagename);
 108      $page = ReadPage($pn, READPAGE_CURRENT);
 109      if (!$page) continue;
 110  
 111      ##  if the page being checked is a blocklist page, stop blocking
 112      if ($pagename == $pn) return;
 113  
 114      ##  If the blocklist page is managed by automatic download,
 115      ##  schedule any new downloads here
 116      if (@$BlocklistDownload[$pn]) {
 117        $bd = &$BlocklistDownload[$pn];
 118        SDVA($bd, array(
 119          'refresh' => $BlocklistDownloadRefresh,
 120          'url' => "http://www.pmwiki.org/blocklists/$pn" ));
 121        if (!@$page['text'] || $page['time'] < $Now - $bd['refresh'])
 122          register_shutdown_function('BlocklistDownload', $pn, getcwd());
 123      }
 124  
 125      ##  If the blocklist is simply a list of regexes to be matched, load 
 126      ##  them into $terms['block'] and continue to the next blocklist page.
 127      ##  Some regexes from remote sites aren't well-formed, so we have
 128      ##  to escape any slashes that aren't already escaped.
 129      if (strpos(@$page['text'], 'blocklist-format: regex') !==false) {
 130        if (preg_match_all('/^([^\\s#].+)/m', $page['text'], $match)) 
 131          foreach($match[0] as $m) {
 132            $m = preg_replace('#(?<!\\\\)/#', '\\/', trim($m));
 133            $terms['block'][] = "/$m/";
 134          }
 135        continue;
 136      }
 137  
 138      ##  Treat the page as a pmwiki-format blocklist page, with
 139      ##  IP addresses and "block:"-style declarations.  First, see
 140      ##  if we need to block the author based on a.b.c.d or a.b.c.*
 141      ##  IP addresses.
 142      $ip = preg_quote($_SERVER['REMOTE_ADDR']);
 143      $ip = preg_replace('/\\d+$/', '($0\\b|\\*)', $ip);
 144      if (preg_match("/\\b$ip/", @$page['text'], $match)) {
 145        $EnablePost = 0;
 146        $IsBlocked = 1;
 147        $WhyBlockedFmt[] = $BlockedMessagesFmt['ip'] . $match[0];
 148      }
 149  
 150      ##  Now we'll load any "block:" or "unblock:" specifications
 151      ##  from the page text.
 152      if (preg_match_all('/(un)?(?:block|regex):(.*)/', @$page['text'], 
 153                         $match, PREG_SET_ORDER)) 
 154        foreach($match as $m) $terms[$m[1].'block'][] = trim($m[2]);
 155    }
 156  
 157    ##  okay, we've loaded all of the terms, now subtract any 'unblock'
 158    ##  terms from the block set.
 159    StopWatch("Blocklist: diff unblock");
 160    $blockterms = array_diff((array)@$terms['block'], (array)@$terms['unblock']);
 161  
 162    ##  go through each of the remaining blockterms and see if it matches the
 163    ##  text -- if so, disable posting and add a message to $WhyBlockedFmt.
 164    StopWatch('Blocklist: blockterms (count='.count($blockterms).')');
 165    $itext = strtolower($text);
 166    foreach($blockterms as $b) {
 167      if ($b{0} == '/') {
 168        if (!preg_match($b, $text)) continue;
 169      } else if (strpos($itext, strtolower($b)) === false) continue;
 170      $EnablePost = 0;
 171      $IsBlocked = 1;
 172      $WhyBlockedFmt[] = $BlockedMessagesFmt['text'] . $b;
 173    }
 174    StopWatch('Blocklist: blockterms done');
 175  
 176    ##  If we came across any reasons to block, let's provide a message
 177    ##  to the author that it was blocked.  If $EnableWhyBlocked is set,
 178    ##  we'll even tell the author why.  :-)
 179    if (@$WhyBlockedFmt) {
 180      $MessagesFmt[] = $BlocklistMessageFmt;
 181      if (IsEnabled($EnableWhyBlocked, 0)) 
 182        foreach((array)$WhyBlockedFmt as $why) 
 183          $MessagesFmt[] = "<pre class='blocklistmessage'>$why</pre>\n";
 184    }
 185    StopWatch("Blocklist: end $pagename");
 186  }
 187  
 188  ##   BlocklistDownload() handles retrieving blocklists from
 189  ##   external sources into PmWiki pages.  If it's able to
 190  ##   download an updated list, it uses that; otherwise it leaves
 191  ##   any existing list alone.
 192  function BlocklistDownload($pagename, $dir = '') {
 193    global $BlocklistDownloadFmt, $BlocklistDownload, $FmtV;
 194  
 195    if ($dir) { flush(); chdir($dir); }
 196    SDV($BlocklistDownloadFmt, "
 197    [@
 198  ## blocklist-note:   NOTE: This page is automatically generated by blocklist.php
 199  ## blocklist-note:   NOTE: Any edits to this page may be lost!
 200  ## blocklist-url:    \$BlocklistDownloadUrl
 201  ## blocklist-when:   \$CurrentTimeISO
 202  #  blocklist-format: \$BlocklistFormat
 203  \$BlocklistData
 204    @]
 205  ");
 206  
 207    ##  get the existing blocklist page
 208    $bd = &$BlocklistDownload[$pagename];
 209    $page = ReadPage($pagename, READPAGE_CURRENT);
 210  
 211    ##  try to retrieve the remote data
 212    $blocklistdata = @file($bd['url']);
 213  
 214    ##  if we didn't get it, and we don't already have text, save a
 215    ##  note in the page so we know what happened
 216    if (!$blocklistdata && !@$page['text']) {
 217      $auf = ini_get('allow_url_fopen');
 218      $blocklistdata = "#### Unable to download blocklist (allow_url_fopen=$auf)";
 219    }
 220  
 221    ##  if we have some new text to save, let's format it and save it
 222    if ($blocklistdata) {
 223      $blocklistdata = implode('', (array)$blocklistdata);
 224      $blocklistdata = preg_replace('/^##blocklist.*/m', '', $blocklistdata);
 225      $FmtV['$BlocklistData'] = $blocklistdata;
 226      $FmtV['$BlocklistDownloadUrl'] = $bd['url'];
 227      $FmtV['$BlocklistFormat'] = $bd['format'];
 228      $page['text'] = FmtPageName($BlocklistDownloadFmt, $pagename);
 229      SDV($page['passwdread'], '@lock');
 230    }
 231  
 232    ##  save our updated(?) blocklist page
 233    WritePage($pagename, $page);
 234  }

title

Description

title

Description

title

Description

title

title

Body