aboutsummaryrefslogtreecommitdiff
path: root/scripts/urlapprove.php
blob: 29d51139b13be95284a8ae4d5459c5041fd1fcaa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<?php if (!defined('PmWiki')) exit();
/*  Copyright 2004-2023 Patrick R. Michaud (pmichaud@pobox.com)
    This file is part of PmWiki; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published
    by the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.  See pmwiki.php for full details.

    This script provides a URL-approval capability.  To enable this
    script, add the following line to a configuration file:

        include_once('scripts/urlapprove.php');

    The URL prefixes to be allowed are stored as patterns in 
    $WhiteUrlPatterns.  This array can be loaded from config.php, or 
    from the wiki pages given by the $ApprovedUrlPagesFmt[] array.  
    Any http: or https: URL that isn't in $WhiteUrlPatterns is rendered 
    using $UnapprovedLinkFmt.

    The script also provides ?action=approveurls and ?action=approvesites, 
    which scan the current page for any new URLs to be automatically added
    the first page of $UrlApprovalPagesFmt.

    Finally, the script will block any post containing more than
    $UnapprovedLinkCountMax unapproved urls in it.  By default this
    is set to a very large number, leaving the posting of unapproved
    urls wide open, but by setting $UnapprovedLinkCountMax to a smaller
    number you can limit the number of unapproved urls that make it into
    a page.  (Wikispammers seem to like to post long lists of urls, while
    more "normal" authors tend to only post a few.)
    
    Script maintained by Petko YOTOV www.pmwiki.org/petko
*/

$LinkFunctions['http:'] = 'LinkHTTP';
$LinkFunctions['https:'] = 'LinkHTTP';
SDV($ApprovedUrlPagesFmt, array('$SiteAdminGroup.ApprovedUrls'));
SDV($UnapprovedLinkFmt,
  "\$LinkText<a class='apprlink' href='{\$PageUrl}?action=approvesites&amp;\$TokenName=\$TokenValue'>$[(approve sites)]</a>");
SDVA($HTMLStylesFmt, array('urlapprove' => '.apprlink { font-size:smaller; }'));
SDV($ApproveUrlPattern,
  "\\bhttps?:[^\\s$UrlExcludeChars]*[^\\s.,?!$UrlExcludeChars]");
$WhiteUrlPatterns = (array)@$WhiteUrlPatterns;
SDV($HandleActions['approveurls'], 'HandleApprove');
SDV($HandleAuth['approveurls'], 'edit');
SDV($HandleActions['approvesites'], 'HandleApprove');
SDV($HandleAuth['approvesites'], 'edit');
SDV($UnapprovedLinkCountMax, 1000000);
array_splice($EditFunctions, array_search('PostPage', $EditFunctions),
  0, 'BlockUnapprovedPosts');

function LinkHTTP($pagename,$imap,$path,$alt,$txt,$fmt=NULL) {
  global $EnableUrlApprovalRequired, $IMap, $WhiteUrlPatterns, $FmtV,
    $UnapprovedLink, $UnapprovedLinkCount, $UnapprovedLinkFmt;
  if (!IsEnabled($EnableUrlApprovalRequired,1))
    return LinkIMap($pagename,$imap,$path,$alt,$txt,$fmt);
  static $havereadpages;
  if (!$havereadpages) { 
    ReadApprovedUrls($pagename); 
    pmtoken(); 
    $havereadpages=true;
  }
  
  $p = str_replace(' ','%20',$path);
  $url = str_replace('$1',$p,$IMap[$imap]);
  if (!isset($UnapprovedLink)) $UnapprovedLink = array();
  foreach((array)$WhiteUrlPatterns as $pat) {
    if (preg_match("!^$pat(/|$)!i",$url))
      return LinkIMap($pagename,$imap,$path,$alt,$txt,$fmt);
  }
  $FmtV['$LinkUrl'] = PUE(str_replace('$1',$path,$IMap[$imap]));
  $FmtV['$LinkText'] = $txt;
  $FmtV['$LinkAlt'] = str_replace(array('"',"'"),array('&#34;','&#39;'),strval(@$alt));
  $UnapprovedLink[] = $url;
  @$UnapprovedLinkCount++;
  return FmtPageName($UnapprovedLinkFmt,$pagename);
}

function ReadApprovedUrls($pagename) {
  global $ApprovedUrlPagesFmt,$ApproveUrlPattern,$WhiteUrlPatterns;
  foreach((array)$ApprovedUrlPagesFmt as $p) {
    $pn = FmtPageName($p, $pagename);
    StopWatch("ReadApprovedUrls $pn begin");
    $apage = ReadPage($pn, READPAGE_CURRENT);
    preg_match_all("/$ApproveUrlPattern/",strval(@$apage['text']),$match);
    foreach($match[0] as $a) {
      $quoted = preg_quote($a,'!');
      $WhiteUrlPatterns[] = preg_replace('!^http\\\\:!', 'https?\\:', $quoted);
    }
    StopWatch("ReadApprovedUrls $pn end");
  }
}

function HandleApprove($pagename, $auth='edit') {
  global $ApproveUrlPattern,$WhiteUrlPatterns,$ApprovedUrlPagesFmt,$action;
  pmtoken(2, true);
  $aname = FmtPageName($ApprovedUrlPagesFmt[0],$pagename);
  $apage = RetrieveAuthPage($aname, $auth);
  if (!$apage) Abort("?cannot edit $aname");
  
  Lock(2);
  $page = ReadPage($pagename);
  $text = preg_replace('/[()]/','',$page['text']);
  preg_match_all("/$ApproveUrlPattern/",$text,$match);
  ReadApprovedUrls($pagename);
  $addpat = array();
  foreach($match[0] as $a) {
    if ($action=='approvesites') 
      $a=preg_replace("!^([^:]+://[^/]+).*$!",'$1',$a);
    $addpat[] = $a;
  }
  if (count($addpat)>0) {
    $new = $apage;
    if (substr($new['text'],-1,1)!="\n") $new['text'].="\n";
    foreach($addpat as $a) {
      foreach((array)$WhiteUrlPatterns as $pat)
        if (preg_match("!^$pat(/|$)!i",$a)) continue 2;
      $urlp = preg_quote($a,'!');
      $WhiteUrlPatterns[] = $urlp;
      $new['text'].="  $a\n";
    }
    $_POST['post'] = 'y';
    PostPage($aname,$apage,$new);
  }
  Redirect($pagename);
}

function BlockUnapprovedPosts($pagename, &$page, &$new) {
  global $EnableUrlApprovalRequired, $UnapprovedLinkCount,
    $UnapprovedLinkCountMax, $EnablePost, $MessagesFmt, $BlockMessageFmt;
  if (!IsEnabled($EnableUrlApprovalRequired, 1)) return;
  if ($UnapprovedLinkCount <= $UnapprovedLinkCountMax) return;
  if ($page['=auth']['admin']) return;
  $EnablePost = 0;
  $MessagesFmt[] = $BlockMessageFmt;
  $MessagesFmt[] = XL('Too many unapproved external links.');
}