Passed
Pull Request — master (#5714)
by David
08:57
created

replace_pre_code()   B

Complexity

Conditions 10
Paths 10

Size

Total Lines 44
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 10
eloc 37
nc 10
nop 2
dl 0
loc 44
rs 7.6666
c 1
b 1
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
// This file is part of BOINC.
3
// http://boinc.berkeley.edu
4
// Copyright (C) 2008 University of California
5
//
6
// BOINC is free software; you can redistribute it and/or modify it
7
// under the terms of the GNU Lesser General Public License
8
// as published by the Free Software Foundation,
9
// either version 3 of the License, or (at your option) any later version.
10
//
11
// BOINC is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
// See the GNU Lesser General Public License for more details.
15
//
16
// You should have received a copy of the GNU Lesser General Public License
17
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
18
19
// Functions that process user-supplied text (e.g. messages)
20
// prior to displaying it to users.
21
// Goals:
22
// - Security (don't send evil javascript)
23
// - obey user preferences
24
// - improve formatting (e.g., convert newlines to <br> tags)
25
26
require_once('../inc/sanitize_html.inc');
27
28
class output_options {
29
    var $bb2html;            // BBCode as HTML? (on)
30
    var $images_as_links;    // Images as hyperlinks? (off)
31
    var $link_popup;        // Links in new windows? (off)
32
    var $nl2br;                // Convert newlines to <br>'s? (on)
33
    var $htmlitems;            // Convert special chars to HTML entities? (on)
34
    var $htmlscrub;            // Scrub "bad" HTML tags? (off)
35
    var $highlight_terms;// Array of terms to be highlighted (off)
36
37
    // Constructor - set the defaults.
38
39
    function __construct() {
40
        $this->bb2html = 1;
41
        $this->images_as_links = 0;
42
        $this->link_popup = 0;
43
        $this->nl2br = 1;
44
        $this->htmlitems = 1;
45
        $this->htmlscrub = 0;
46
        $this->highlight_terms = 0;
47
        return true;
48
    }
49
50
    // Define the terms to be highlighted (for use with searches and such)
51
52
    function setHighlightTerms($terms) {
53
        if (is_array($terms)) {
54
            $this->highlight_terms = $terms;
55
        } else {
56
            return false;
57
        }
58
        return true;
59
    }
60
}
61
62
// Do the actual transformation of the text.
63
// TODO: Make this part of the above class.
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
64
65
function output_transform($text, $options = NULL) {
66
    // Options is a output_options object, defined above
67
    if (!$options) {
68
        $options = new output_options; // Defaults in the class definition
69
    }
70
    if ($options->htmlitems) {
71
        $text = htmlspecialchars($text, ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE);
72
    }
73
    if (is_array($options->highlight_terms)) {
74
        $text = highlight_terms($text, $options->highlight_terms);
75
    }
76
//    if ($options->htmlscrub) {
77
//        $text = sanitize_html($text);
78
//    }
79
    if ($options->nl2br) {
80
        $text = nl2br($text);
81
    }
82
    if ($options->bb2html) {
83
        $text = bb2html($text);
84
    }
85
    if ($options->images_as_links) {
86
        $text = image_as_link($text);
87
    }
88
    if ($options->link_popup) {
89
        $text = externalize_links($text);
90
    }
91
    return $text;
92
}
93
94
function get_output_options($user) {
95
    $options = new output_options();
96
    if ($user) {
97
        if ($user->prefs->images_as_links) $options->images_as_links = 1;
98
        if ($user->prefs->link_popup) $options->link_popup = 1;
99
    }
100
    return $options;
101
}
102
103
// Converts bbcode to HTML
104
// If $export is true, don't use BOINC CSS
105
106
function substr2($s, $n1, $n2) {
107
    return substr($s, $n1, $n2-$n1);
108
}
109
110
// process non-nestable constructs: [pre] and [code]
111
//
112
function replace_pre_code($text, $export) {
113
    $out = '';
114
    $pos = 0;
115
    while (true) {
116
        $n1 = strpos($text, '[code]', $pos);
117
        $n2 = strpos($text, '[pre]', $pos);
118
        if ($n1 === false && $n2 === false) {
119
            $out .= substr($text, $pos);
120
            break;
121
        }
122
        if ($n1 === false) $n1 = 9999;
123
        if ($n2 === false) $n2 = 9999;
124
        if ($n1 < $n2) {
125
            $n = $n1;
126
            $tag = '[code]';
127
            $tag2 = '[/code]';
128
        } else {
129
            $n = $n2;
130
            $tag = '[pre]';
131
            $tag2 = '[/pre]';
132
        }
133
        $out .= substr2($text, $pos, $n);
134
        $n2 = strpos($text, $tag2, $n);
135
        $n += strlen($tag);
136
        if (!$n2) {
137
            $out .= substr($text, $n);
138
            break;
139
        }
140
        $x = substr2($text, $n, $n2);
141
        $x = remove_br($x);
142
        $x = htmlspecialchars($x, ENT_COMPAT, "UTF-8", false);
143
        $x = str_replace("[", "&#91;", $x);
144
        if ($export) {
145
            if ($tag == '[pre]') {
146
                $out .= "<pre>$x</pre>";
147
            } else {
148
                $out .= "<code>$x</code>";
149
            }
150
        } else {
151
            $out .= "<pre style=\"white-space:pre-wrap;\">$x</pre>";
152
        }
153
        $pos = $n2 + strlen($tag2);
154
    }
155
    return $out;
156
}
157
158
// process nestable constructs
159
//
160
function bb2html_aux($text, $export) {
161
    $urlregex = "(?:\"?)(?:(http\:\/\/)?)([^\[\"<\ ]+)(?:\"?)";
162
    // NOTE:
163
    // This matches https:// too; I don't understand why.
164
    // sample results:
165
    // Array
166
    // (
167
    //     [0] => [img]https://a.b.c[/img]
168
    //     [1] =>
169
    //     [2] => https://a.b.c
170
    // )
171
    // Array
172
    // (
173
    //     [0] => [img]http://a.b.c[/img]
174
    //     [1] => http://
175
    //     [2] => a.b.c
176
    // )
177
178
    $httpsregex = "(?:\"?)https\:\/\/([^\[\"<\ ]+)(?:\"?)";
179
    // List of allowable tags
180
    $bbtags = array (
0 ignored issues
show
Coding Style introduced by
There must be no space between the "array" keyword and the opening parenthesis
Loading history...
181
        "@\[b\](.*?)\[/b\]@is",
182
        "@\[i\](.*?)\[/i\]@is",
183
        "@\[u\](.*?)\[/u\]@is",
184
        "@\[s\](.*?)\[/s\]@is",
185
        "@\[sup\](.*?)\[/sup\]@is",
186
        "@\[url=$httpsregex\](.*?)\[/url\]@is",
187
        "@\[url\]$httpsregex\[/url\]@is",
188
        "@\[link=$urlregex\](.*?)\[/link\]@is",
189
        "@\[link\]$urlregex\[/link\]@is",
190
        "@\[url=$urlregex\](.*?)\[/url\]@is",
191
        "@\[url\]$urlregex\[/url\]@is",
192
        "@\[quote=(.*?)\](.*?)\[/quote\]@is",
193
        "@\[quote\](.*?)\[/quote\]@is",
194
        "@\[list\](.*?)\[/list\]@is",
195
        "@\[list=1\](.*?)\[/list\]@is",
196
        "@\[img\]$urlregex\[/img\]@is",
197
        "@\[sm_img\]$urlregex\[/sm_img\]@is",
198
        "@\[color=(?:\"?)(.{3,8})(?:\"?)\](.*?)\[/color\]@is",
199
        "@((?:<ol>|<ul>).*?)\n\*([^\n]+)\n(.*?(</ol>|</ul>))@is",
200
        "@\[size=([1-9]|[0-2][0-9])\](.*?)\[/size\]@is",
201
        "@\[mailto\](.*?)\[/mailto\]@is",
202
        "@\[email\](.*?)\[/email\]@is",
203
        "@\[github\](?:\#|ticket:)(\d+)\[/github\]@is",
204
        "@\[github\]wiki:(.*?)\[/github\]@is",
205
    );
206
207
    // What the above tags are turned in to
208
    if ($export) {
209
        $htmltags = array (
0 ignored issues
show
Coding Style introduced by
There must be no space between the "array" keyword and the opening parenthesis
Loading history...
210
            "<b>\\1</b>",
211
            "<i>\\1</i>",
212
            "<u>\\1</u>",
213
            "<s>\\1</s>",
214
            "<sup>\\1</sup>",
215
            "<a href=\"https://\\1\" rel=\"nofollow\">\\2</a>",
216
            "<a href=\"https://\\1\" rel=\"nofollow\">https://\\1</a>",
217
            "<a href=\"http://\\2\" rel=\"nofollow\">\\3</a>",
218
            "<a href=\"http://\\2\" rel=\"nofollow\">http://\\2</a>",
219
            "<a href=\"http://\\2\" rel=\"nofollow\">\\3</a>",
220
            "<a href=\"http://\\2\" rel=\"nofollow\">http://\\2</a>",
221
            "<i>\\1 wrote:</i><blockquote>\\2</blockquote>",
222
            "<blockquote>\\1</blockquote>",
223
            "<ul>\\1</ul><p>",
224
            "<ol>\\1</ol><p>",
225
            "<img hspace=\"8\" src=\"\\1\\2\"> ",
226
            "<img hspace=\"8\" width=400 src=\"\\1\\2\"> ",
227
            "<font color=\"\\1\">\\2</font>",
228
            "\\1<li>\\2\n\\3",
229
            "<span style=\"font-size: \\1px;\">\\2</span>",
230
            "<a href=\"mailto:\\1\">\\1</a>",
231
            "<a href=\"mailto:\\1\">\\1</a>",
232
            "<a href=\"https://github.com/BOINC/boinc/issues/\\1\">#\\1</a>",
233
            "<a href=\"https://github.com/BOINC/boinc/wiki/\\1\">\\1</a>",
234
        );
235
    } else {
236
        $htmltags = array (
0 ignored issues
show
Coding Style introduced by
There must be no space between the "array" keyword and the opening parenthesis
Loading history...
237
            "<b>\\1</b>",
238
            "<i>\\1</i>",
239
            "<u>\\1</u>",
240
            "<s>\\1</s>",
241
            "<sup>\\1</sup>",
242
            "<a href=\"https://\\1\" rel=\"nofollow\">\\2</a>",
243
            "<a href=\"https://\\1\" rel=\"nofollow\">https://\\1</a>",
244
            "<a href=\"http://\\2\" rel=\"nofollow\">\\3</a>",
245
            "<a href=\"http://\\2\" rel=\"nofollow\">http://\\2</a>",
246
            "<a href=\"http://\\2\" rel=\"nofollow\">\\3</a>",
247
            "<a href=\"http://\\2\" rel=\"nofollow\">http://\\2</a>",
248
            "<em>\\1 wrote:</em><blockquote>\\2</blockquote>",
249
            "<blockquote>\\1</blockquote>",
250
            "<ul>\\1</ul><p>",
251
            "<ol>\\1</ol><p>",
252
            "<img hspace=\"8\" class=\"img-responsive\" src=\"\\1\\2\"> ",
253
            "<img hspace=\"8\" width=400 src=\"\\1\\2\"> ",
254
            "<font color=\"\\1\">\\2</font>",
255
            "\\1<li>\\2\n\\3",
256
            "<span style=\"font-size: \\1px;\">\\2</span>",
257
            "<a href=\"mailto:\\1\">\\1</a>",
258
            "<a href=\"mailto:\\1\">\\1</a>",
259
            "<a href=\"https://github.com/BOINC/boinc/issues/\\1\">#\\1</a>",
260
            "<a href=\"https://github.com/BOINC/boinc/wiki/\\1\">\\1</a>",
261
        );
262
    }
263
264
    // Do the actual replacing - iterations for nested items
265
    $lasttext = "";
266
    $i = 0;
267
    // $i<1000 to prevent DoS
268
    while ($text != $lasttext && $i<1000) {
269
        $lasttext = $text;
270
        $text = preg_replace($bbtags, $htmltags, $text);
271
        $i = $i + 1;
0 ignored issues
show
Coding Style introduced by
Increment operators should be used where possible; found "$i = $i + 1;" but expected "$i++"
Loading history...
272
    }
273
    $text = str_replace("<ul>", '<ul style="word-break:break-word;">', $text);
274
    $text = str_replace("<ol>", '<ol style="word-break:break-word;">', $text);
275
    return $text;
276
}
277
278
function bb2html($text, $export=false) {
279
    $text = replace_pre_code($text, $export);
280
    return bb2html_aux($text, $export);
281
}
282
283
// Remove any <br> tags added by nl2br which are not wanted,
284
// for example inside <pre> containers
285
// The original \n was retained after the br when it was added
286
//
287
function remove_br($text){
288
    return str_replace("<br />", "", $text);
289
}
290
291
// Make links open in new windows.
292
//
293
function externalize_links($text) {
294
    // TODO:  Convert this to PCRE
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
295
    $i=0;
296
    $linkpos=true;
297
    $out = "";
298
    while (true){
299
        //Find a link
300
        //
301
        $linkpos=strpos($text, "<a ", $i);
302
        if ($linkpos===false) break;
303
304
        //Replace with target='_new'
305
        //
306
        $out .= substr($text, $i, $linkpos-$i)."<a target=\"_new\" ";
307
        $i = $linkpos+3;
308
    }
309
    $out .= substr($text, $i);
310
    return $out;
311
}
312
313
// Converts image tags to links to the images.
314
315
function image_as_link($text){
316
    /* This function depends on sanitized HTML */
317
    // Build some regex (should be a *lot* faster)
318
    $pattern = '@<img([\S\s]+?)src=([^>]+?)>@si';
319
    $replacement = '<a href=${2}>[Image link]</a>'; // Turns that URL into a hyperlink
320
    $text = preg_replace($pattern, $replacement, $text);
321
    return $text;
322
}
323
324
// Highlight terms in text (most likely used with searches)
325
326
function highlight_terms($text, $terms) {
327
    $search = $terms;
328
    $replace = array();
329
330
    foreach ($search as $key => $value) {
331
        $replace[$key] = "<span class=\"mark\">".$value."</span>";
332
    }
333
    return str_ireplace($search, $replace, $text);
334
}
335
336
$cvs_version_tracker[]="\$Id$";  //Generated automatically - do not edit
337
?>
338