XHP:接口

2018-10-17 11:09 更新

有兩個(gè)重要的接口中XHP,XHPRoot和XHPChild; 在函數(shù)中添加類型注釋時(shí),您將需要使用這些注釋。

XHPRoot

該XHPRoot接口由所有XHP對象實(shí)現(xiàn); 在實(shí)踐中,這意味著:

  • :x:element 子類 - 這些是重用(并組合)現(xiàn)有XHP類的類
  • :x:primitive子類 - 這些定義基本元素,例如:x:frag和所有基本的HTML元素
  • 所述的實(shí)施方式XHPUnsafeRenderable如下所述接口

XHPChild

XHP呈現(xiàn)樹結(jié)構(gòu),該接口定義樹的有效子節(jié)點(diǎn); 這包括:

  • 所有的實(shí)現(xiàn) XHPRoot
  • 字符串,整數(shù),浮點(diǎn)數(shù)
  • 上述任何一個(gè)數(shù)組

盡管字符串,整數(shù),浮點(diǎn)數(shù)和數(shù)組都不是對象,但是類型instanceof檢查器和HHVM都認(rèn)為它們可以實(shí)現(xiàn)這個(gè)接口 - 無論是對于參數(shù)/返回類型還是用于檢查。

高級接口

雖然XHP的安全默認(rèn)功能通常是有益的,但偶爾需要繞過它們; 最常見的情況是:

  • 遷移到XHP時(shí)需要嵌入另一個(gè)模板系統(tǒng)的輸出。
  • 需要從其他來源嵌入HTML,例如Markdown或BBCode渲染器。

XHP通常會(huì)阻礙:

  • 轉(zhuǎn)換所有變量,包括您的HTML代碼。
  • 執(zhí)行子關(guān)系 - XHP對象不能被標(biāo)記為允許HTML字符串子對象。

該XHPUnsafeRenderable和XHPAlwaysValidChild接口允許繞過這些安全機(jī)制。

XHPUnsafeRenderable

如果您需要渲染原始HTML字符串,請將其包裝在實(shí)現(xiàn)此接口的類中,并提供一種toHTMLString(): string方法:

<?hh
/* YOU PROBABLY SHOULDN'T DO THIS
 *
 * Even with a scary (and accurate) name, it tends to be over-used.
 * See below for an alternative.
 */
class ExamplePotentialXSSSecurityHole implements XHPUnsafeRenderable {
  public function __construct(
    private string $html,
  ) {
  }

  public function toHTMLString(): string {
    return $this->html;
  }
}

echo (
  <div class="markdown">
    {new ExamplePotentialXSSSecurityHole(
      HHVM\UserDocumentation\XHP\Examples\md_render('Markdown goes here')
    )}
  </div>
)."\n";

我們不提供此接口的實(shí)現(xiàn),因?yàn)橥ㄓ脤?shí)現(xiàn)往往被過度使用 - 相反,考慮進(jìn)行更具體的實(shí)現(xiàn):

<?hh
class ExampleMarkdownXHPWrapper implements XHPUnsafeRenderable {
  private string $html;
  public function __construct(
    string $markdown_source,
  ) {
    $this->html = HHVM\UserDocumentation\XHP\Examples\md_render(
      $markdown_source
    );
  }

  public function toHTMLString(): string {
    return $this->html;
  }
}

echo (
  <div class="markdown">
    {new ExampleMarkdownXHPWrapper('Markdown goes here')}
  </div>
)."\n";

XHPAlwaysValidChild

可以通過實(shí)現(xiàn)此接口來繞過XHP的子級驗(yàn)證。實(shí)現(xiàn)此接口的大多數(shù)類也是實(shí)現(xiàn)XHPUnsafeRenderable,因?yàn)樽畛R姷男枨笫钱?dāng)另一個(gè)渲染或模板系統(tǒng)生成子代時(shí)。

這也可以由XHP對象來實(shí)現(xiàn),但這通常表示應(yīng)該用類別替換子類規(guī)范。這個(gè)界面是故意打破XHP安全性的一部分,所以應(yīng)盡量少用。

Example

<?hh
final class XHPUnsafeExample implements XHPUnsafeRenderable {
  public function toHTMLString(): string {
    return '<script>'.$_GET['I_LOVE_XSS'].'</script>';
  }
}

$inputs = Map {
  '<div />' => <div />,
  '<x:frag />' => <x:frag />,
  '"foo"' => 'foo',
  '3' => 3,
  'true' => true,
  'null' => null,
  'new stdClass()' => new stdClass(),
  '[<li />, <li />, <li />]' => [<li />, <li />, <li />],
  'XHPUnsafeExample' => new XHPUnsafeExample(),
};

$max_label_len = max($inputs->mapWithKey(($k, $_) ==> strlen($k)));
print str_repeat(' ', $max_label_len + 1)." | XHPRoot | XHPChild\n";
print str_repeat('-', $max_label_len + 1)."-|---------|----------\n";

foreach ($inputs as $label => $input) {
  printf(
    " %{$max_label_len}s | %-7s | %s\n",
    $label,
    $input instanceof XHPRoot ? 'yes' : 'no',
    $input instanceof XHPChild ? 'yes' : 'no',
  );
}

Output

                          | XHPRoot | XHPChild
--------------------------|---------|----------
                  <div /> | yes     | yes
               <x:frag /> | yes     | yes
                    "foo" | no      | yes
                        3 | no      | yes
                     true | no      | no
                     null | no      | no
           new stdClass() | no      | no
 [<li />, <li />, <li />] | no      | yes
         XHPUnsafeExample | no      | yes
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)