public function solveTag($invocation, TexyHtml $el, $isStart, $forceEmpty = NULL) { $tx = $this->texy; $allowedTags = $tx->allowedTags; if (!$allowedTags) { return FALSE; } $name = $el->getName(); $lower = strtolower($name); if (isset($tx->dtd[$lower]) || $name === strtoupper($name)) { $name = $lower; $el->setName($name); } if (is_array($allowedTags)) { if (!isset($allowedTags[$name])) { return FALSE; } $allowedAttrs = $allowedTags[$name]; } else { if ($forceEmpty) { $el->setName($name, TRUE); } $allowedAttrs = Texy::ALL; } if (!$isStart) { return $el; } $elAttrs =& $el->attrs; if (!$allowedAttrs) { $elAttrs = array(); } elseif (is_array($allowedAttrs)) { $allowedAttrs = array_flip($allowedAttrs); foreach ($elAttrs as $key => $foo) { if (!isset($allowedAttrs[$key])) { unset($elAttrs[$key]); } } } $tmp = $tx->_classes; if (isset($elAttrs['class'])) { if (is_array($tmp)) { $elAttrs['class'] = explode(' ', $elAttrs['class']); foreach ($elAttrs['class'] as $key => $value) { if (!isset($tmp[$value])) { unset($elAttrs['class'][$key]); } } } elseif ($tmp !== Texy::ALL) { $elAttrs['class'] = NULL; } } if (isset($elAttrs['id'])) { if (is_array($tmp)) { if (!isset($tmp['#' . $elAttrs['id']])) { $elAttrs['id'] = NULL; } } elseif ($tmp !== Texy::ALL) { $elAttrs['id'] = NULL; } } if (isset($elAttrs['style'])) { $tmp = $tx->_styles; if (is_array($tmp)) { $styles = explode(';', $elAttrs['style']); $elAttrs['style'] = NULL; foreach ($styles as $value) { $pair = explode(':', $value, 2); $prop = trim($pair[0]); if (isset($pair[1]) && isset($tmp[strtolower($prop)])) { $elAttrs['style'][$prop] = $pair[1]; } } } elseif ($tmp !== Texy::ALL) { $elAttrs['style'] = NULL; } } if ($name === 'img') { if (!isset($elAttrs['src'])) { return FALSE; } if (!$tx->checkURL($elAttrs['src'], Texy::FILTER_IMAGE)) { return FALSE; } $tx->summary['images'][] = $elAttrs['src']; } elseif ($name === 'a') { if (!isset($elAttrs['href']) && !isset($elAttrs['name']) && !isset($elAttrs['id'])) { return FALSE; } if (isset($elAttrs['href'])) { if ($tx->linkModule->forceNoFollow && strpos($elAttrs['href'], '//') !== FALSE) { if (isset($elAttrs['rel'])) { $elAttrs['rel'] = (array) $elAttrs['rel']; } $elAttrs['rel'][] = 'nofollow'; } if (!$tx->checkURL($elAttrs['href'], Texy::FILTER_ANCHOR)) { return FALSE; } $tx->summary['links'][] = $elAttrs['href']; } } elseif (preg_match('#^h[1-6]#i', $name)) { $tx->headingModule->TOC[] = array('el' => $el, 'level' => (int) substr($name, 1), 'type' => 'html'); } $el->validateAttrs($tx->dtd); return $el; }
/** * Finish invocation. * * @param TexyHandlerInvocation handler invocation * @param TexyHtml element * @param bool is start tag? * @param bool is empty? * @return TexyHtml|string|FALSE */ public function solveTag($invocation, TexyHtml $el, $isStart, $forceEmpty = NULL) { $tx = $this->texy; // tag & attibutes $allowedTags = $tx->allowedTags; // speed-up if (!$allowedTags) { return FALSE; } // all tags are disabled // convert case $name = $el->getName(); $lower = strtolower($name); if (isset($tx->dtd[$lower]) || $name === strtoupper($name)) { // complete UPPER convert to lower $name = $lower; $el->setName($name); } if (is_array($allowedTags)) { if (!isset($allowedTags[$name])) { return FALSE; } $allowedAttrs = $allowedTags[$name]; // allowed attrs } else { // allowedTags === Texy::ALL if ($forceEmpty) { $el->setName($name, TRUE); } $allowedAttrs = Texy::ALL; // all attrs are allowed } // end tag? we are finished if (!$isStart) { return $el; } $elAttrs =& $el->attrs; // process attributes if (!$allowedAttrs) { $elAttrs = array(); } elseif (is_array($allowedAttrs)) { // skip disabled $allowedAttrs = array_flip($allowedAttrs); foreach ($elAttrs as $key => $foo) { if (!isset($allowedAttrs[$key])) { unset($elAttrs[$key]); } } } // apply allowedClasses $tmp = $tx->_classes; // speed-up if (isset($elAttrs['class'])) { if (is_array($tmp)) { $elAttrs['class'] = explode(' ', $elAttrs['class']); foreach ($elAttrs['class'] as $key => $value) { if (!isset($tmp[$value])) { unset($elAttrs['class'][$key]); } } // id & class are case-sensitive } elseif ($tmp !== Texy::ALL) { $elAttrs['class'] = NULL; } } // apply allowedClasses for ID if (isset($elAttrs['id'])) { if (is_array($tmp)) { if (!isset($tmp['#' . $elAttrs['id']])) { $elAttrs['id'] = NULL; } } elseif ($tmp !== Texy::ALL) { $elAttrs['id'] = NULL; } } // apply allowedStyles if (isset($elAttrs['style'])) { $tmp = $tx->_styles; // speed-up if (is_array($tmp)) { $styles = explode(';', $elAttrs['style']); $elAttrs['style'] = NULL; foreach ($styles as $value) { $pair = explode(':', $value, 2); $prop = trim($pair[0]); if (isset($pair[1]) && isset($tmp[strtolower($prop)])) { // CSS is case-insensitive $elAttrs['style'][$prop] = $pair[1]; } } } elseif ($tmp !== Texy::ALL) { $elAttrs['style'] = NULL; } } if ($name === 'img') { if (!isset($elAttrs['src'])) { return FALSE; } if (!$tx->checkURL($elAttrs['src'], Texy::FILTER_IMAGE)) { return FALSE; } $tx->summary['images'][] = $elAttrs['src']; } elseif ($name === 'a') { if (!isset($elAttrs['href']) && !isset($elAttrs['name']) && !isset($elAttrs['id'])) { return FALSE; } if (isset($elAttrs['href'])) { if ($tx->linkModule->forceNoFollow && strpos($elAttrs['href'], '//') !== FALSE) { if (isset($elAttrs['rel'])) { $elAttrs['rel'] = (array) $elAttrs['rel']; } $elAttrs['rel'][] = 'nofollow'; } if (!$tx->checkURL($elAttrs['href'], Texy::FILTER_ANCHOR)) { return FALSE; } $tx->summary['links'][] = $elAttrs['href']; } } elseif (preg_match('#^h[1-6]#i', $name)) { $tx->headingModule->TOC[] = array('el' => $el, 'level' => (int) substr($name, 1), 'type' => 'html'); } $el->validateAttrs($tx->dtd); return $el; }