Issues (42)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/TextFilter/TShortcode.php (9 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Mos\TextFilter;
4
5
/**
6
 * Shortcode to format when working with text.
7
 *
8
 */
9
trait TShortcode
10
{
11
    /**
12
     * Shortcode to quicker format text as HTML.
13
     *
14
     * @param string $text text to be converted.
15
     *
16
     * @return string the formatted text.
17
     */
18 1
    public function shortCode($text)
19
    {
20
        /* Needs PHP 7
21
        $patternsAndCallbacks = [
22
            "/\[(FIGURE)[\s+](.+)\]/" => function ($match) {
23
                return self::ShortCodeFigure($matches[2]);
24
            },
25
            "/(```([\w]*))\n([^`]*)```[\n]{1}/s" => function ($match) {
26
                return $this->syntaxHighlightGeSHi($matches[3], $matches[2]);
27
            },
28
        ];
29
30
        return preg_replace_callback_array($patternsAndCallbacks, $text);
31
        */
32
33
        $patterns = [
34 1
            "/\[(FIGURE)[\s+](.+)\]/",
35
            //'/\[(YOUTUBE) src=(.+) width=(.+) caption=(.+)\]/',
36 1
            "/\[(YOUTUBE)[\s+](.+)\]/",
37 1
            "/\[(CODEPEN)[\s+](.+)\]/",
38 1
            "/\[(ASCIINEMA)[\s+](.+)\]/",
39 1
            "/\[(BOOK)[\s+](.+)\]/",
40 1
            //"/(```)([\w]*)\n([.]*)```[\n]{1}/s",
41 1
            "/(```)([\w]*)\n(.*?)```\n/s",
42
            '/\[(INFO)\]/',
43 1
            '/\[(\/INFO)\]/',
44 1
            '/\[(WARNING)\]/',
45 1
            '/\[(\/WARNING)\]/',
46 1
        ];
47 1
48 1
        return preg_replace_callback(
49
            $patterns,
50
            function ($matches) {
51
                switch ($matches[1]) {
52
                    case "FIGURE":
53
                        return self::shortCodeFigure($matches[2]);
54
                    break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
55
56
                    case "YOUTUBE":
57
                        return self::shortCodeYoutube($matches[2]);
58
                    break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
59
60
                    case "CODEPEN":
61
                        return self::shortCodeCodepen($matches[2]);
62
                    break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
63
64
                    case "ASCIINEMA":
65
                        return self::shortCodeAsciinema($matches[2]);
66
                    break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
67
68
                    case "BOOK":
69
                        return self::shortCodeBook($matches[2]);
70
                    break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
71
72
                    case "```":
73
                        //return $this->syntaxHighlightGeSHi($matches[3], $matches[2]);
74
                        return $this->syntaxHighlightJs($matches[3], $matches[2]);
75 1
                    break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
76
77 1
                    case 'INFO':
78
                        return <<<EOD
79
<div class="info">
80
    <span class="icon fa-stack fa-lg">
81
        <i class="fa fa-circle fa-stack-2x"></i>
82
        <i class="fa fa-info fa-stack-1x fa-inverse" aria-hidden="true"></i>
83
    </span>
84
    <div markdown=1>
85
EOD;
86
                        break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
87
88
                    case 'WARNING':
89
                        return <<<EOD
90 1
<div class="warning">
91
    <span class="icon fa-stack fa-lg">
92 1
        <i class="fa fa-circle fa-stack-2x"></i>
93
        <i class="fa fa-exclamation-triangle fa-stack-1x fa-inverse" aria-hidden="true"></i>
94 1
    </span>
95 1
    <div markdown=1>
96 1
EOD;
97 1
                        break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
98
99
                    case '/INFO':
100 1
                    case '/WARNING':
101 1
                        return "</div></div>";
102 1
                        break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
103
104 1
                    default:
105
                        return "{$matches[1]} is unknown shortcode.";
106 1
                }
107
            },
108
            $text
109
        );
110
    }
111
112
113
114
    /**
115
     * Init shortcode handling by preparing the option list to an array,
116
     * for those using arguments.
117
     *
118
     * @param string $options for the shortcode.
119
     *
120
     * @return array with all the options.
121
     */
122
    public static function shortCodeInit($options)
123
    {
124
        preg_match_all('/[a-zA-Z0-9]+="[^"]+"|\S+/', $options, $matches);
125
126
        $res = array();
127
        foreach ($matches[0] as $match) {
128
            $pos = strpos($match, '=');
129
            if ($pos === false) {
130
                $res[$match] = true;
131
            } else {
132
                $key = substr($match, 0, $pos);
133
                $val = trim(substr($match, $pos+1), '"');
134
                $res[$key] = $val;
135
            }
136
        }
137
138
        return $res;
139
    }
140
141
142
143
    /**
144
     * Shortcode for [YOUTUBE].
145
     *
146
     * Usage example: [YOUTUBE src=id-for-the-tube width=630 caption=""]
147
     *
148
     * @param string $options for the shortcode.
149
     *
150
     * @return array with all the options.
151
     */
152
    public static function shortCodeYoutube($options)
153
    {
154
        $options= array_merge(
155
            [
156
                "id"    => null,
157
                "class" => null,
158
                "src" => null,
159 1
                "list" => null,
160
                "time" => null,
161
                "width" => 600,
162 1
                "ratio" => 16/9,
163
                "caption" => null,
164 1
            ],
165 1
            self::ShortCodeInit($options)
166 1
        );
167 1
        extract($options, EXTR_SKIP);
168 1
169 1
        $id = $id ? " id=\"$id\"" : null;
170 1
        $class = $class ? " class=\"figure $class\"" : " class=\"figure\"";
171 1
        $list = $list ? "?listType=playlist&amp;list=$list" : null;
172 1
        $time = $time ? "#t=$time" : null;
173 1
        $height = ceil($width / $ratio);
174 1
175 1
        //$caption = t("Figure: !CAPTION", ["!CAPTION" => $caption]);
176
        if ($caption) {
177 1
            $caption = "<figcaption markdown=1>{$caption}</figcaption>";
178 1
        }
179 1
180
        // @codingStandardsIgnoreStart
181 1
        $html = <<<EOD
182 1
<figure{$id}{$class}>
183 1
<iframe width="$width" height="$height" src="https://www.youtube.com/embed/{$src}{$list}{$time}" frameborder="0" allowfullscreen></iframe>
184
{$caption}
185 1
</figure>
186 1
EOD;
187 1
        // @codingStandardsIgnoreEnd
188 1
189
        return $html;
190 1
    }
191 1
192 1
193 1
194 1
    /**
195 1
     * Shortcode for [CODEPEN].
196
     *
197
     * Usage example: [CODEPEN src=id-for-the-pen user="mosbth"
198 1
     * tab="js,result" caption="caption"]
199 1
     *
200 1
     * @param string $options for the shortcode.
201 1
     *
202 1
     * @return array with all the options.
203
     */
204 1
    public static function shortCodeCodepen($options)
205
    {
206
        $options= array_merge(
207
            [
208
                "id"    => null,
209
                "class" => null,
210
                "src" => null,
211
                "user" => null,
212
                "title" => null,
213
                "tab" => "result",
214
                "theme" => 0,
215
                "height" => 300,
216
                "width" => "100%",
217
                "caption" => null,
218
            ],
219
            self::ShortCodeInit($options)
220
        );
221
        extract($options, EXTR_SKIP);
222
223
        $id = $id ? " id=\"$id\"" : null;
224
        $class = $class ? " class=\"figure figure-codepen $class\"" : " class=\"figure figure-codepen\"";
225
226
        //$caption = t("Figure: !CAPTION", ["!CAPTION" => $caption]);
227
        if ($caption) {
228
            $caption = "<figcaption markdown=1>{$caption}</figcaption>";
229
        }
230
231
        // @codingStandardsIgnoreStart
232
        $html = <<<EOD
233
<figure{$id}{$class} width="$width">
234
<p data-height="$height" data-theme-id="$theme" data-slug-hash="$src" data-default-tab="$tab" data-user="$user" data-embed-version="2" data-pen-title="$title" class="codepen">See the <a href="https://codepen.io/$user/pen/$src/">Pen</a> on <a href="https://codepen.io">CodePen</a>.</p>
235
{$caption}
236
</figure>
237
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
238
EOD;
239
        // @codingStandardsIgnoreEnd
240
241
        return $html;
242
    }
243
244
245
246
    /**
247
     * Shortcode for <figure>.
248
     *
249
     * Usage example: [FIGURE src="img/home/me.jpg" caption="Me" alt="Bild på mig" nolink="nolink"]
250
     *
251
     * @param string $options for the shortcode.
252
     *
253
     * @return array with all the options.
254
     */
255
    public static function shortCodeFigure($options)
256
    {
257
        // Merge incoming options with default and expose as variables
258
        $options= array_merge(
259
            [
260
                "id"    => null,
261
                "class" => null,
262
                "src"   => null,
263
                "title" => null,
264
                "alt"   => null,
265
                "caption" => null,
266
                "href"  => null,
267
                "nolink" => false,
268
            ],
269
            self::ShortCodeInit($options)
270
        );
271
        extract($options, EXTR_SKIP);
272
273
        $id = $id ? " id=\"$id\"" : null;
274
        $class = $class ? " class=\"figure $class\"" : " class=\"figure\"";
275
        $title = $title ? " title=\"$title\"" : null;
276
277
        if (!$alt && $caption) {
278
            $alt = $caption;
279
        }
280
281
        if (!$href) {
282
            $pos = strpos($src, "?");
283
            $href = $pos ? substr($src, 0, $pos) : $src;
284
        }
285
286
        $start = null;
287
        $end = null;
288
        if (!$nolink) {
289
            $start = "<a href=\"{$href}\">";
290
            $end = "</a>";
291
        }
292
293
        if ($caption) {
294
            $caption = "<figcaption markdown=1>{$caption}</figcaption>";
295
        }
296
297
        $html = <<<EOD
298
<figure{$id}{$class}>
299
{$start}<img src="{$src}" alt="{$alt}"{$title}/>{$end}
300
{$caption}
301
</figure>
302
EOD;
303
304
        return $html;
305
    }
306
307
308
309
    /**
310
     * Shortcode for [asciinema].
311
     *
312
     * @param string $code the code to process.
313
     * @param string $options for the shortcode.
314
     * @return array with all the options.
315
     */
316
    public static function shortCodeAsciinema($options)
317
    {
318
        // Merge incoming options with default and expose as variables
319
        $options= array_merge(
320
            [
321
                "id" => null,
322
                "class" => null,
323
                "src" => null,
324
                "title" => null,
325
                "caption" => null,
326
            ],
327
            self::ShortCodeInit($options)
328
        );
329
        extract($options, EXTR_SKIP);
330
331
        $id = $id ? " id=\"$id\"" : null;
332
        $class = $class ? " class=\"figure asciinema $class\"" : " class=\"figure asciinema\"";
333
        $title = $title ? " title=\"$title\"" : null;
334
335
        $html = <<<EOD
336
<figure{$id}{$class}$title>
337
<script type="text/javascript" src="https://asciinema.org/a/{$src}.js" id="asciicast-{$src}" async></script>
338
<figcaption markdown=1>{$caption}</figcaption>
339
</figure>
340
EOD;
341
342
        return $html;
343
    }
344
345
346
347
    /**
348
     * Shortcode for [book].
349
     *
350
     * @param string $code the code to process.
351
     * @param string $options for the shortcode.
352
     * @return array with all the options.
353
     */
354
    public static function shortCodeBook($options)
355
    {
356
        // Merge incoming options with default and expose as variables
357
        $options= array_merge(
358
            [
359
                "isbn" => null,
360
            ],
361
            self::ShortCodeInit($options)
362
        );
363
        extract($options, EXTR_SKIP);
364
365
        $stores = [
366
            "BTH" => "http://bth.summon.serialssolutions.com/?#!/search?ho=t&amp;q={$isbn}",
367
            "Libris" => "http://libris.kb.se/hitlist?q={$isbn}",
368
            "Google Books" => "http://books.google.com/books?q={$isbn}",
369
            "Bokus" => "http://www.bokus.com/bok/{$isbn}",
370
            "Adlibris" => "http://www.adlibris.com/se/product.aspx?isbn={$isbn}",
371
            "Amazon" => "http://www.amazon.com/s/ref=nb_ss?url=field-keywords={$isbn}",
372
            "Barnes&Noble" => "http://search.barnesandnoble.com/booksearch/ISBNInquiry.asp?r=1&IF=N&EAN={$isbn}",
373
        ];
374
375
        $html = null;
376
        foreach ($stores as $key => $val) {
377
            $html .= "<a href='$val'>$key</a> &bull; ";
378
        }
379
        return substr($html, 0, -8);
380
    }
381
382
383
384
    /**
385
     * Shortcode for including a SVG-image inside a <figure>.
386
     *
387
     * @param string $code the code to process.
388
     * @param string $options for the shortcode.
389
     * @return array with all the options.
390
     */
391
/*    public static function ShortCodeSVGFigure($options) {
392
        // Merge incoming options with default and expose as variables
393
        $options= array_merge(
394
            [
395
                "id"    => null,
396
                "class" => null,
397
                "src"   => null,
398
                "title" => null,
399
                "alt"   => null,
400
                "caption" => null,
401
                "href"  => null,
402
                "nolink" => false,
403
                //'path' => null,
404
            ],
405
            self::ShortCodeInit($options)
406
        );
407
        extract($options, EXTR_SKIP);
408
409
        $id = $id ? " id=\"$id\"" : null;
410
        $class = $class ? " class=\"figure $class\"" : " class=\"figure\"";
411
        $title = $title ? " title=\"$title\"" : null;
412
413
        if (!$alt && $caption) {
414
            $alt = $caption;
415
        }
416
417
        if (!$href) {
418
            $pos = strpos($src, "?");
419
            $href = $pos ? substr($src, 0, $pos) : $src;
420
        }
421
422
        $start = null;
423
        $end = null;
424
        if (!$nolink) {
425
            $start = "<a href=\"{$href}\">";
426
            $end = "</a>";
427
        }
428
429
        // Import the file containing the svg-image
430
        /*
431
        $svg = null;
432
433
        if($path[0] != '/') {
434
        $path = self::$dir . '/' . $path;
435
        }
436
437
        if(is_file($path)) {
438
        $svg = file_get_contents($path);
439
        }
440
        else {
441
        $svg = "No such file: $path";
442
        }
443
        $html = <<<EOD
444
        <figure{$id}{$class}>
445
        {$svg}
446
        <figcaption markdown=1>{$caption}</figcaption>
447
        </figure>
448
        EOD;*/
449
/*
450
        $html = <<<EOD
451
<figure{$id}{$class}>
452
{$start}<img src="{$src}" alt="{$alt}"{$title}/>{$end}
453
<figcaption markdown=1>{$caption}</figcaption>
454
</figure>
455
EOD;
456
457
        return $html;*/
458
/*    }
459
*/
460
461
462
463
/**
464
 * Shorttags to to quicker format text as HTML.
465
 *
466
 * @param string text text to be converted.
467
 * @return string the formatted text.
468
 */
469
/*public static function ShortTags($text) {
470
  $callback = function($matches) {
471
    switch($matches[1]) {
472
      case 'IMG':
473
        $caption = t('Image: ');
474
        $pos = strpos($matches[2], '?');
475
        $href = $pos ? substr($matches[2], 0, $pos) : $matches[2];
476
        $src = htmlspecialchars($matches[2]);
477
        return <<<EOD
478
<figure>
479
<a href='{$href}'><img src='{$src}' alt='{$matches[3]}' /></a>
480
<figcaption markdown=1>{$caption}{$matches[3]}</figcaption>
481
</figure>
482
EOD;
483
484
      case 'IMG2':
485
        $caption = null; //t('Image: ');
486
        $pos = strpos($matches[2], '?');
487
        $href = $pos ? substr($matches[2], 0, $pos) : $matches[2];
488
        $src = htmlspecialchars($matches[2]);
489
        return <<<EOD
490
<figure class="{$matches[4]}">
491
<a href='{$href}'><img src='{$src}' alt='{$matches[3]}' /></a>
492
<figcaption markdown=1>{$caption}{$matches[3]}</figcaption>
493
</figure>
494
EOD;
495
      case 'BOOK':
496
        $isbn = $matches[2];
497
        $stores = array(
498
          'BTH' => "http://bth.summon.serialssolutions.com/?#!/search?ho=t&amp;q={$isbn}",
499
          'Libris' => "http://libris.kb.se/hitlist?q={$isbn}",
500
          'Google Books' => "http://books.google.com/books?q={$isbn}",
501
          'Bokus' => "http://www.bokus.com/bok/{$isbn}",
502
          'Adlibris' => "http://www.adlibris.com/se/product.aspx?isbn={$isbn}",
503
          'Amazon' => "http://www.amazon.com/s/ref=nb_ss?url=field-keywords={$isbn}",
504
          'Barnes&Noble' => "http://search.barnesandnoble.com/booksearch/ISBNInquiry.asp?r=1&IF=N&EAN={$isbn}",
505
        );
506
        $html = null;
507
        foreach($stores as $key => $val) {
508
          $html .= "<a href='$val'>$key</a> &bull; ";
509
        }
510
        return substr($html, 0, -8);
511
      break;
512
513
      case 'YOUTUBE':
514
        $caption = t('Figure: ');
515
        $height = ceil($matches[3] / (16/9));
516
        return <<<EOD
517
<figure>
518
<iframe width='{$matches[3]}' height='{$height}' src="http://www.youtube.com/embed/{$matches[2]}" frameborder="0"
519
allowfullscreen></iframe>
520
<figcaption>{$caption}{$matches[4]}</figcaption>
521
</figure>
522
EOD;
523
      break;
524
      
525
      case 'syntax=': return CTextFilter::SyntaxHighlightGeSHi($matches[3], $matches[2]); break;
526
      case '```': return CTextFilter::SyntaxHighlightGeSHi($matches[3], $matches[2]); break;
527
      //case 'syntax=': return "<pre>" . highlight_string($matches[3], true) . "</pre>"; break;
528
      //case 'INCL':  include($matches[2]); break;
529
      case 'INFO':  return "<div class='info' markdown=1>"; break;
530
      case '/INFO': return "</div>"; break;
531
      case 'BASEURL': return CLydia::Instance()->request->base_url; break;
532
      case 'FIGURE': return CTextFilter::ShortCodeFigure($matches[2]); break;
533
      case 'FIGURE-SVG': return CTextFilter::ShortCodeSVGFigure($matches[2]); break;
534
      case 'ASCIINEMA': return CTextFilter::ShortCodeAsciinema($matches[2]); break;
535
      default: return "{$matches[1]} IS UNKNOWN SHORTTAG."; break;
536
    }
537
  };
538
  $patterns = array(
539
    '#\[(BASEURL)\]#',
540
    //'/\[(AUTHOR) name=(.+) email=(.+) url=(.+)\]/',
541
    '/\[(FIGURE)[\s+](.+)\]/',
542
    '/\[(FIGURE-SVG)[\s+](.+)\]/',
543
    '/\[(ASCIINEMA)[\s+](.+)\]/',
544
    '/\[(IMG) src=(.+) alt=(.+)\]/',
545
    '/\[(IMG2) src=(.+) alt="(.+)" class="(.+)"\]/',
546
    '/\[(BOOK) isbn=(.+)\]/',
547
    '/\[(YOUTUBE) src=(.+) width=(.+) caption=(.+)\]/',
548
    '/~~~(syntax=)(php|html|html5|css|sql|javascript|bash)\n([^~]+)\n~~~/s',
549
    '/(```)(php|html|html5|css|sql|javascript|bash|text|txt|python)\n([^`]+)\n```/s',
550
    //'/\[(INCL)/s*([^\]+)/',
551
    '#\[(INFO)\]#', '#\[(/INFO)\]#',
552
  );
553
554
  $ret = preg_replace_callback($patterns, $callback, $text);
555
  return $ret;
556
}
557
*/
558
}
559