~ubuntu-branches/ubuntu/vivid/phabricator/vivid-proposed

« back to all changes in this revision

Viewing changes to libphutil/src/markup/engine/remarkup/markuprule/PhutilRemarkupRule.php

  • Committer: Package Import Robot
  • Author(s): Richard Sellam
  • Date: 2014-10-23 20:49:26 UTC
  • mfrom: (0.2.1) (0.1.1)
  • Revision ID: package-import@ubuntu.com-20141023204926-vq80u1op4df44azb
Tags: 0~git20141023-1
Initial release (closes: #703046)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
 
 
3
/**
 
4
 * @stable
 
5
 */
 
6
abstract class PhutilRemarkupRule {
 
7
 
 
8
  private $engine;
 
9
  private $replaceCallback;
 
10
 
 
11
  public function setEngine(PhutilRemarkupEngine $engine) {
 
12
    $this->engine = $engine;
 
13
    return $this;
 
14
  }
 
15
 
 
16
  public function getEngine() {
 
17
    return $this->engine;
 
18
  }
 
19
 
 
20
  public function getPriority() {
 
21
    return 500.0;
 
22
  }
 
23
 
 
24
  abstract public function apply($text);
 
25
 
 
26
  public function getPostprocessKey() {
 
27
    return spl_object_hash($this);
 
28
  }
 
29
 
 
30
  public function didMarkupText() {
 
31
    return;
 
32
  }
 
33
 
 
34
  protected function replaceHTML($pattern, $callback, $text) {
 
35
    $this->replaceCallback = $callback;
 
36
    return phutil_safe_html(preg_replace_callback(
 
37
      $pattern,
 
38
      array($this, 'replaceHTMLCallback'),
 
39
      phutil_escape_html($text)));
 
40
  }
 
41
 
 
42
  private function replaceHTMLCallback($match) {
 
43
    return phutil_escape_html(call_user_func(
 
44
      $this->replaceCallback,
 
45
      array_map('phutil_safe_html', $match)));
 
46
  }
 
47
 
 
48
 
 
49
  /**
 
50
   * Safely generate a tag.
 
51
   *
 
52
   * In Remarkup contexts, it's not safe to use arbitrary text in tag
 
53
   * attributes: even though it will be escaped, it may contain replacement
 
54
   * tokens which are then replaced with markup.
 
55
   *
 
56
   * This method acts as @{function:phutil_tag}, but checks attributes before
 
57
   * using them.
 
58
   *
 
59
   * @param   string              Tag name.
 
60
   * @param   dict<string, wild>  Tag attributes.
 
61
   * @param   wild                Tag content.
 
62
   * @return  PhutilSafeHTML      Tag object.
 
63
   */
 
64
  protected function newTag($name, array $attrs, $content = null) {
 
65
    foreach ($attrs as $key => $attr) {
 
66
      if ($attr !== null) {
 
67
        $attrs[$key] = $this->assertFlatText($attr);
 
68
      }
 
69
    }
 
70
 
 
71
    return phutil_tag($name, $attrs, $content);
 
72
  }
 
73
 
 
74
  /**
 
75
   * Assert that a text token is flat (it contains no replacement tokens).
 
76
   *
 
77
   * Because tokens can be replaced with markup, it is dangerous to use
 
78
   * arbitrary input text in tag attributes. Normally, rule precedence should
 
79
   * prevent this. Asserting that text is flat before using it as an attribute
 
80
   * provides an extra layer of security.
 
81
   *
 
82
   * Normally, you can call @{method:newTag} rather than calling this method
 
83
   * directly. @{method:newTag} will check attributes for you.
 
84
   *
 
85
   * @param   wild    Ostensibly flat text.
 
86
   * @return  string  Flat text.
 
87
   */
 
88
  protected function assertFlatText($text) {
 
89
    $text = (string)hsprintf('%s', phutil_safe_html($text));
 
90
    $rich = (strpos($text, PhutilRemarkupBlockStorage::MAGIC_BYTE) !== false);
 
91
    if ($rich) {
 
92
      throw new Exception(
 
93
        pht(
 
94
          'Remarkup rule precedence is dangerous: rendering text with tokens '.
 
95
          'as flat text!'));
 
96
    }
 
97
 
 
98
    return $text;
 
99
  }
 
100
 
 
101
  /**
 
102
   * Check whether text is flat (contains no replacement tokens) or not.
 
103
   *
 
104
   * @param   wild  Ostensibly flat text.
 
105
   * @return  bool  True if the text is flat.
 
106
   */
 
107
  protected function isFlatText($text) {
 
108
    $text = (string)hsprintf('%s', phutil_safe_html($text));
 
109
    return (strpos($text, PhutilRemarkupBlockStorage::MAGIC_BYTE) === false);
 
110
  }
 
111
 
 
112
}