HTML Arıtma: şartlı nitelikleri dayalı bir eleman çıkarma

3 Cevap php

the HTML Purifier smoketest, 'hatalı biçimlendirilmiş' URI'larını bazen bir nitelik daha az çapa etiketi, örneğin geride bırakmak atılır başına

<a href="javascript:document.location='http://www.google.com/'">XSS</a> olur <a>XSS</a>

... Yanı sıra protokole soyunmuş olması, örneğin

<a href="http://1113982867/">XSS</a> olur <a href="http:/">XSS</a>

Per se, sorunsuz olsa da, biraz çirkin. Bunun yerine düzenli ifadeler ile bu dışarı atmak için çalışıyor, ben HTML Arıtma kendi kütüphane yetenekleri / enjektör / plug-ins / whathaveyou kullanmak umuyordum.

Point of reference: Handling attributes

Şartlı HTMLPurifier bir attribute kaldırılması kolaydır. Burada kütüphane yöntemi ile HTMLPurifier_AttrTransform sınıfını sunar confiscateAttr() .

Ben şahsen başına confiscateAttr() , I do use an HTMLPurifier_AttrTransform işlevselliğini kullanmak yok iken this thread target="_blank" tüm çapa eklemek.

// more configuration stuff up here
$htmlDef = $htmlPurifierConfiguration->getHTMLDefinition(true);
$anchor  = $htmlDef->addBlankElement('a');
$anchor->attr_transform_post[] = new HTMLPurifier_AttrTransform_Target();
// purify down here

HTMLPurifier_AttrTransform_Target tabii, çok basit bir sınıftır.

class HTMLPurifier_AttrTransform_Target extends HTMLPurifier_AttrTransform
{
    public function transform($attr, $config, $context) {
        // I could call $this->confiscateAttr() here to throw away an
        // undesired attribute
        $attr['target'] = '_blank';
        return $attr;
    }
}

O kısmı doğal, bir cazibe gibi çalışır.

Handling elements

Belki HTMLPurifier_TagTransform de yeterince sert şaşı değilim, ya da yanlış yere (ler) arıyorum, ya da genel olarak bunu anlamakta amn't, ama şartlı kaldırmak için bir yol anlamaya gibi olamaz elements.

Etkisiyle, bir şey söyle:

// more configuration stuff up here
$htmlDef = $htmlPurifierConfiguration->getHTMLDefinition(true);
$anchor  = $htmlDef->addElementHandler('a');
$anchor->elem_transform_post[] = new HTMLPurifier_ElementTransform_Cull();
// add target as per 'point of reference' here
// purify down here

İtlaf sınıf confiscateElement() ability, or comparable, wherein I could check for a missing href nitelik veya içeriği ile href niteliği olan bir şey uzanan http:/.

HTMLPurifier_Filter

Ben bir filtre oluşturabilirsiniz anlıyorum, ama örnekler (Youtube.php ve ExtractStyleBlocks.php) ben gerçekten oldukça kaçınmak istiyorum hangi, bu düzenli ifadeler kullanarak, if it is at all possible olurdum öneririz. Ben HTML Arıtma mükemmel ayrıştırma yetenekleri kullanan bir yerleşik veya yarı-onboard çözüm için umut ediyorum.

null HTMLPurifier_AttrTransform maalesef onu kesmiyor bir çocuk sınıfta döndürülüyor.

Herkes herhangi bir akıllı fikir var, ya da ben regexes şaşırıp? :)

3 Cevap

Başarı! Ambush Commander and mcgrailm in another question, ben şimdi bir hilariously basit bir çözüm kullanıyorum teşekkürler:

// a bit of context
$htmlDef = $this->configuration->getHTMLDefinition(true);
$anchor  = $htmlDef->addBlankElement('a');

// HTMLPurifier_AttrTransform_RemoveLoneHttp strips 'href="http:/"' from
// all anchor tags (see first post for class detail)
$anchor->attr_transform_post[] = new HTMLPurifier_AttrTransform_RemoveLoneHttp();

// this is the magic! We're making 'href' a required attribute (note the
// asterisk) - now HTML Purifier removes <a></a>, as well as
// <a href="http:/"></a> after HTMLPurifier_AttrTransform_RemoveLoneHttp
// is through with it!
$htmlDef->addAttribute('a', 'href*', new HTMLPurifier_AttrDef_URI());

Çalışır, bu works, bahahahaHAHAHAHAnhͥͤͫ̀ğͮ͑̆ͦó̓̉ͬ͋h́ͧ̆̈́̉ğ̈́͐̈a̾̈́̑ͨô̔̄̑̇g̀̄h̘̝͊̐ͩͥ̋ͤ͛g̦̣̙̙̒̀ͥ̐̔ͅo̤̣hg͓̈́͋̇̓́̆a͖̩̯̥͕͂̈̐ͮ̒o̶ͬ̽̀̍ͮ̾ͮ͢҉̩͉̘͓̙̦̩̹͍̹̠̕g̵̡͔̙͉̱̠̙̩͚͑ͥ̎̓͛̋͗̍̽͋͑̈́̚...! * Manik kahkaha, sesler gurgling, yüzünde bir gülümseme * ile üzerinden salmalar

Eğer bir TagTransform ile öğeleri kaldırmak olamaz gerçeği bir uygulama ayrıntı olmuş görünüyor. nodes (sadece etiketi daha smidge üst seviyede) kaldırılması için klasik mekanizma olsa bir Enjektör kullanmaktır.

Her neyse, aradığınız işlevsellik özel parça zaten% AutoFormat.RemoveEmpty olarak uygulanır

Inceleme için, bu benim şimdiki çözümdür. Bu çalışır, ancak tamamen HTML Arıtma atlar.

/**
 * Removes <a></a> and <a href="http:/"></a> tags from the purified
 * HTML.
 * @todo solve this with an injector?
 * @param string $purified The purified HTML
 * @return string The purified HTML, sans pointless anchors.
 */
private function anchorCull($purified)
{
    if (empty($purified)) return '';
    // re-parse HTML
    $domTree = new DOMDocument();
    $domTree->loadHTML($purified);
    // find all anchors (even good ones)
    $anchors = $domTree->getElementsByTagName('a');
    // collect bad anchors (destroying them in this loop breaks the DOM)
    $destroyNodes = array();
    for ($i = 0; ($i < $anchors->length); $i++) {
        $anchor = $anchors->item($i);
        $href   = $anchor->attributes->getNamedItem('href');
        // <a></a>
        if (is_null($href)) {
            $destroyNodes[] = $anchor;
        // <a href="http:/"></a>
        } else if ($href->nodeValue == 'http:/') {
            $destroyNodes[] = $anchor;
        }
    }
    // destroy the collected nodes
    foreach ($destroyNodes as $node) {
        // preserve content
        $retain = $node->childNodes;
        for ($i = 0; ($i < $retain->length); $i++) {
            $rnode = $retain->item($i);
            $node->parentNode->insertBefore($rnode, $node);
        }
        // actually destroy the node
        $node->parentNode->removeChild($node);
    }
    // strip out HTML out of DOM structure string
    $html = $domTree->saveHTML();
    $begin = strpos($html, '<body>') + strlen('<body>');
    $end   = strpos($html, '</body>');
    return substr($html, $begin, $end - $begin);
}

Ben hala daha ziyade bu iyi bir HTML Arıtma çözüm olurdu, bu yüzden, sadece bir heads-up gibi, bu cevap öz-kabul kadar sona ermeyecek. Ama durum hiç iyi cevap etrafında geliyor biter, en azından benzer sorunları olanlar yardımcı olabilir. :)