CasperSecurity

Current Path : /var/www/hrms.uiet.co.in/vendor/dompdf/dompdf/src/FrameReflower/
Upload File :
Current File : /var/www/hrms.uiet.co.in/vendor/dompdf/dompdf/src/FrameReflower/AbstractFrameReflower.php

<?php
/**
 * @package dompdf
 * @link    https://github.com/dompdf/dompdf
 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
 */
namespace Dompdf\FrameReflower;

use Dompdf\Dompdf;
use Dompdf\Helpers;
use Dompdf\Frame;
use Dompdf\Frame\Factory;
use Dompdf\FrameDecorator\AbstractFrameDecorator;
use Dompdf\FrameDecorator\Block;

/**
 * Base reflower class
 *
 * Reflower objects are responsible for determining the width and height of
 * individual frames.  They also create line and page breaks as necessary.
 *
 * @package dompdf
 */
abstract class AbstractFrameReflower
{

    /**
     * Frame for this reflower
     *
     * @var AbstractFrameDecorator
     */
    protected $_frame;

    /**
     * Cached min/max child size
     *
     * @var array
     */
    protected $_min_max_child_cache;

    /**
     * Cached min/max size
     *
     * @var array
     */
    protected $_min_max_cache;

    /**
     * AbstractFrameReflower constructor.
     * @param AbstractFrameDecorator $frame
     */
    function __construct(AbstractFrameDecorator $frame)
    {
        $this->_frame = $frame;
        $this->_min_max_child_cache = null;
        $this->_min_max_cache = null;
    }

    /**
     * @return Dompdf
     */
    function get_dompdf()
    {
        return $this->_frame->get_dompdf();
    }

    public function reset(): void
    {
        $this->_min_max_child_cache = null;
        $this->_min_max_cache = null;
    }

    /**
     * Determine the actual containing block for absolute and fixed position.
     *
     * https://www.w3.org/TR/CSS21/visudet.html#containing-block-details
     */
    protected function determine_absolute_containing_block(): void
    {
        $frame = $this->_frame;
        $style = $frame->get_style();

        switch ($style->position) {
            case "absolute":
                $parent = $frame->find_positioned_parent();
                if ($parent !== $frame->get_root()) {
                    $parent_style = $parent->get_style();
                    $parent_padding_box = $parent->get_padding_box();
                    //FIXME: an accurate measure of the positioned parent height
                    //       is not possible until reflow has completed;
                    //       we'll fall back to the parent's containing block,
                    //       which is wrong for auto-height parents
                    if ($parent_style->height === "auto") {
                        $parent_containing_block = $parent->get_containing_block();
                        $containing_block_height = $parent_containing_block["h"] -
                            (float)$parent_style->length_in_pt([
                                $parent_style->margin_top,
                                $parent_style->margin_bottom,
                                $parent_style->border_top_width,
                                $parent_style->border_bottom_width
                            ], $parent_containing_block["w"]);
                    } else {
                        $containing_block_height = $parent_padding_box["h"];
                    }
                    $frame->set_containing_block($parent_padding_box["x"], $parent_padding_box["y"], $parent_padding_box["w"], $containing_block_height);
                    break;
                }
            case "fixed":
                $initial_cb = $frame->get_root()->get_first_child()->get_containing_block();
                $frame->set_containing_block($initial_cb["x"], $initial_cb["y"], $initial_cb["w"], $initial_cb["h"]);
                break;
            default:
                // Nothing to do, containing block already set via parent
                break;
        }
    }

    /**
     * Collapse frames margins
     * http://www.w3.org/TR/CSS21/box.html#collapsing-margins
     */
    protected function _collapse_margins(): void
    {
        $frame = $this->_frame;

        // Margins of float/absolutely positioned/inline-level elements do not collapse
        if (!$frame->is_in_flow() || $frame->is_inline_level()
            || $frame->get_root() === $frame || $frame->get_parent() === $frame->get_root()
        ) {
            return;
        }

        $cb = $frame->get_containing_block();
        $style = $frame->get_style();

        $t = $style->length_in_pt($style->margin_top, $cb["w"]);
        $b = $style->length_in_pt($style->margin_bottom, $cb["w"]);

        // Handle 'auto' values
        if ($t === "auto") {
            $style->set_used("margin_top", 0.0);
            $t = 0.0;
        }

        if ($b === "auto") {
            $style->set_used("margin_bottom", 0.0);
            $b = 0.0;
        }

        // Collapse vertical margins:
        $n = $frame->get_next_sibling();
        if ( $n && !($n->is_block_level() && $n->is_in_flow()) ) {
            while ($n = $n->get_next_sibling()) {
                if ($n->is_block_level() && $n->is_in_flow()) {
                    break;
                }

                if (!$n->get_first_child()) {
                    $n = null;
                    break;
                }
            }
        }

        if ($n) {
            $n_style = $n->get_style();
            $n_t = (float)$n_style->length_in_pt($n_style->margin_top, $cb["w"]);

            $b = $this->get_collapsed_margin_length($b, $n_t);
            $style->set_used("margin_bottom", $b);
            $n_style->set_used("margin_top", 0.0);
        }

        // Collapse our first child's margin, if there is no border or padding
        if ($style->border_top_width == 0 && $style->length_in_pt($style->padding_top) == 0) {
            $f = $this->_frame->get_first_child();
            if ( $f && !($f->is_block_level() && $f->is_in_flow()) ) {
                while ($f = $f->get_next_sibling()) {
                    if ($f->is_block_level() && $f->is_in_flow()) {
                        break;
                    }

                    if (!$f->get_first_child()) {
                        $f = null;
                        break;
                    }
                }
            }

            // Margins are collapsed only between block-level boxes
            if ($f) {
                $f_style = $f->get_style();
                $f_t = (float)$f_style->length_in_pt($f_style->margin_top, $cb["w"]);

                $t = $this->get_collapsed_margin_length($t, $f_t);
                $style->set_used("margin_top", $t);
                $f_style->set_used("margin_top", 0.0);
            }
        }

        // Collapse our last child's margin, if there is no border or padding
        if ($style->border_bottom_width == 0 && $style->length_in_pt($style->padding_bottom) == 0) {
            $l = $this->_frame->get_last_child();
            if ( $l && !($l->is_block_level() && $l->is_in_flow()) ) {
                while ($l = $l->get_prev_sibling()) {
                    if ($l->is_block_level() && $l->is_in_flow()) {
                        break;
                    }

                    if (!$l->get_last_child()) {
                        $l = null;
                        break;
                    }
                }
            }

            // Margins are collapsed only between block-level boxes
            if ($l) {
                $l_style = $l->get_style();
                $l_b = (float)$l_style->length_in_pt($l_style->margin_bottom, $cb["w"]);

                $b = $this->get_collapsed_margin_length($b, $l_b);
                $style->set_used("margin_bottom", $b);
                $l_style->set_used("margin_bottom", 0.0);
            }
        }
    }

    /**
     * Get the combined (collapsed) length of two adjoining margins.
     *
     * See http://www.w3.org/TR/CSS21/box.html#collapsing-margins.
     *
     * @param float $l1
     * @param float $l2
     *
     * @return float
     */
    private function get_collapsed_margin_length(float $l1, float $l2): float
    {
        if ($l1 < 0 && $l2 < 0) {
            return min($l1, $l2); // min(x, y) = - max(abs(x), abs(y)), if x < 0 && y < 0
        }
        
        if ($l1 < 0 || $l2 < 0) {
            return $l1 + $l2; // x + y = x - abs(y), if y < 0
        }
        
        return max($l1, $l2);
    }

    /**
     * Handle relative positioning according to
     * https://www.w3.org/TR/CSS21/visuren.html#relative-positioning.
     *
     * @param AbstractFrameDecorator $frame The frame to handle.
     */
    protected function position_relative(AbstractFrameDecorator $frame): void
    {
        $style = $frame->get_style();

        if ($style->position === "relative") {
            $cb = $frame->get_containing_block();
            $top = $style->length_in_pt($style->top, $cb["h"]);
            $right = $style->length_in_pt($style->right, $cb["w"]);
            $bottom = $style->length_in_pt($style->bottom, $cb["h"]);
            $left = $style->length_in_pt($style->left, $cb["w"]);

            // FIXME RTL case:
            // if ($left !== "auto" && $right !== "auto") $left = -$right;
            if ($left === "auto" && $right === "auto") {
                $left = 0;
            } elseif ($left === "auto") {
                $left = -$right;
            }

            if ($top === "auto" && $bottom === "auto") {
                $top = 0;
            } elseif ($top === "auto") {
                $top = -$bottom;
            }

            $frame->move($left, $top);
        }
    }

    /**
     * @param Block|null $block
     */
    abstract function reflow(Block $block = null);

    /**
     * Resolve the `min-width` property.
     *
     * Resolves to 0 if not set or if a percentage and the containing-block
     * width is not defined.
     *
     * @param float|null $cbw Width of the containing block.
     *
     * @return float
     */
    protected function resolve_min_width(?float $cbw): float
    {
        $style = $this->_frame->get_style();
        $min_width = $style->min_width;

        return $min_width !== "auto"
            ? $style->length_in_pt($min_width, $cbw ?? 0)
            : 0.0;
    }

    /**
     * Resolve the `max-width` property.
     *
     * Resolves to `INF` if not set or if a percentage and the containing-block
     * width is not defined.
     *
     * @param float|null $cbw Width of the containing block.
     *
     * @return float
     */
    protected function resolve_max_width(?float $cbw): float
    {
        $style = $this->_frame->get_style();
        $max_width = $style->max_width;

        return $max_width !== "none"
            ? $style->length_in_pt($max_width, $cbw ?? INF)
            : INF;
    }

    /**
     * Resolve the `min-height` property.
     *
     * Resolves to 0 if not set or if a percentage and the containing-block
     * height is not defined.
     *
     * @param float|null $cbh Height of the containing block.
     *
     * @return float
     */
    protected function resolve_min_height(?float $cbh): float
    {
        $style = $this->_frame->get_style();
        $min_height = $style->min_height;

        return $min_height !== "auto"
            ? $style->length_in_pt($min_height, $cbh ?? 0)
            : 0.0;
    }

    /**
     * Resolve the `max-height` property.
     *
     * Resolves to `INF` if not set or if a percentage and the containing-block
     * height is not defined.
     *
     * @param float|null $cbh Height of the containing block.
     *
     * @return float
     */
    protected function resolve_max_height(?float $cbh): float
    {
        $style = $this->_frame->get_style();
        $max_height = $style->max_height;

        return $max_height !== "none"
            ? $style->length_in_pt($style->max_height, $cbh ?? INF)
            : INF;
    }

    /**
     * Get the minimum and maximum preferred width of the contents of the frame,
     * as requested by its children.
     *
     * @return array A two-element array of min and max width.
     */
    public function get_min_max_child_width(): array
    {
        if (!is_null($this->_min_max_child_cache)) {
            return $this->_min_max_child_cache;
        }

        $low = [];
        $high = [];

        for ($iter = $this->_frame->get_children(); $iter->valid(); $iter->next()) {
            $inline_min = 0;
            $inline_max = 0;

            // Add all adjacent inline widths together to calculate max width
            while ($iter->valid() && ($iter->current()->is_inline_level() || $iter->current()->get_style()->display === "-dompdf-image")) {
                /** @var AbstractFrameDecorator */
                $child = $iter->current();
                $child->get_reflower()->_set_content();
                $minmax = $child->get_min_max_width();

                if (in_array($child->get_style()->white_space, ["pre", "nowrap"], true)) {
                    $inline_min += $minmax["min"];
                } else {
                    $low[] = $minmax["min"];
                }

                $inline_max += $minmax["max"];
                $iter->next();
            }

            if ($inline_min > 0) {
                $low[] = $inline_min;
            }
            if ($inline_max > 0) {
                $high[] = $inline_max;
            }

            // Skip children with absolute position
            if ($iter->valid() && !$iter->current()->is_absolute()) {
                /** @var AbstractFrameDecorator */
                $child = $iter->current();
                $child->get_reflower()->_set_content();
                list($low[], $high[]) = $child->get_min_max_width();
            }
        }

        $min = count($low) ? max($low) : 0;
        $max = count($high) ? max($high) : 0;

        return $this->_min_max_child_cache = [$min, $max];
    }

    /**
     * Get the minimum and maximum preferred content-box width of the frame.
     *
     * @return array A two-element array of min and max width.
     */
    public function get_min_max_content_width(): array
    {
        return $this->get_min_max_child_width();
    }

    /**
     * Get the minimum and maximum preferred border-box width of the frame.
     *
     * Required for shrink-to-fit width calculation, as used in automatic table
     * layout, absolute positioning, float and inline-block. This provides a
     * basic implementation. Child classes should override this or
     * `get_min_max_content_width` as necessary.
     *
     * @return array An array `[0 => min, 1 => max, "min" => min, "max" => max]`
     *         of min and max width.
     */
    public function get_min_max_width(): array
    {
        if (!is_null($this->_min_max_cache)) {
            return $this->_min_max_cache;
        }

        $style = $this->_frame->get_style();
        [$min, $max] = $this->get_min_max_content_width();

        // Account for margins, borders, and padding
        $dims = [
            $style->padding_left,
            $style->padding_right,
            $style->border_left_width,
            $style->border_right_width,
            $style->margin_left,
            $style->margin_right
        ];

        // The containing block is not defined yet, treat percentages as 0
        $delta = (float) $style->length_in_pt($dims, 0);
        $min += $delta;
        $max += $delta;

        return $this->_min_max_cache = [$min, $max, "min" => $min, "max" => $max];
    }

    /**
     * Parses a CSS string containing quotes and escaped hex characters
     *
     * @param $string string The CSS string to parse
     * @param $single_trim
     * @return string
     */
    protected function _parse_string($string, $single_trim = false)
    {
        if ($single_trim) {
            $string = preg_replace('/^[\"\']/', "", $string);
            $string = preg_replace('/[\"\']$/', "", $string);
        } else {
            $string = trim($string, "'\"");
        }

        $string = str_replace(["\\\n", '\\"', "\\'"],
            ["", '"', "'"], $string);

        // Convert escaped hex characters into ascii characters (e.g. \A => newline)
        $string = preg_replace_callback("/\\\\([0-9a-fA-F]{0,6})/",
            function ($matches) { return \Dompdf\Helpers::unichr(hexdec($matches[1])); },
            $string);
        return $string;
    }

    /**
     * Parses a CSS "quotes" property
     *
     * https://www.w3.org/TR/css-content-3/#quotes
     *
     * @return array An array of pairs of quotes
     */
    protected function _parse_quotes(): array
    {
        $quotes = $this->_frame->get_style()->quotes;

        if ($quotes === "none") {
            return [];
        }

        if ($quotes === "auto") {
            // TODO: Use typographically appropriate quotes for the current
            // language here
            return [['"', '"'], ["'", "'"]];
        }

        // Matches quote types
        $re = '/(\'[^\']*\')|(\"[^\"]*\")/';

        // Split on spaces, except within quotes
        if (!preg_match_all($re, $quotes, $matches, PREG_SET_ORDER)) {
            return [];
        }

        $quotes_array = [];
        foreach ($matches as $_quote) {
            $quotes_array[] = $this->_parse_string($_quote[0], true);
        }

        return array_chunk($quotes_array, 2);
    }

    /**
     * Parses the CSS "content" property
     *
     * https://www.w3.org/TR/CSS21/generate.html#content
     *
     * @return string The resulting string
     */
    protected function _parse_content(): string
    {
        $style = $this->_frame->get_style();
        $content = $style->content;

        if ($content === "normal" || $content === "none") {
            return "";
        }

        $quotes = $this->_parse_quotes();
        $text = "";

        foreach ($content as $val) {
            // String
            if (in_array(mb_substr($val, 0, 1), ['"', "'"], true)) {
                $text .= $this->_parse_string($val);
                continue;
            }

            $val = mb_strtolower($val);

            // Keywords
            if ($val === "open-quote") {
                // FIXME: Take quotation depth into account
                if (isset($quotes[0][0])) {
                    $text .= $quotes[0][0];
                }
                continue;
            } elseif ($val === "close-quote") {
                // FIXME: Take quotation depth into account
                if (isset($quotes[0][1])) {
                    $text .= $quotes[0][1];
                }
                continue;
            } elseif ($val === "no-open-quote") {
                // FIXME: Increment quotation depth
                continue;
            } elseif ($val === "no-close-quote") {
                // FIXME: Decrement quotation depth
                continue;
            }

            // attr()
            if (mb_substr($val, 0, 5) === "attr(") {
                $i = mb_strpos($val, ")");
                if ($i === false) {
                    continue;
                }

                $attr = trim(mb_substr($val, 5, $i - 5));
                if ($attr === "") {
                    continue;
                }

                $text .= $this->_frame->get_parent()->get_node()->getAttribute($attr);
                continue;
            }

            // counter()/counters()
            if (mb_substr($val, 0, 7) === "counter") {
                // Handle counter() references:
                // http://www.w3.org/TR/CSS21/generate.html#content

                $i = mb_strpos($val, ")");
                if ($i === false) {
                    continue;
                }

                preg_match('/(counters?)(^\()*?\(\s*([^\s,]+)\s*(,\s*["\']?([^"\'\)]*)["\']?\s*(,\s*([^\s)]+)\s*)?)?\)/i', $val, $args);
                $counter_id = $args[3];

                if (strtolower($args[1]) === "counter") {
                    // counter(name [,style])
                    if (isset($args[5])) {
                        $type = trim($args[5]);
                    } else {
                        $type = "decimal";
                    }
                    $p = $this->_frame->lookup_counter_frame($counter_id);

                    $text .= $p->counter_value($counter_id, $type);
                } elseif (strtolower($args[1]) === "counters") {
                    // counters(name, string [,style])
                    if (isset($args[5])) {
                        $string = $this->_parse_string($args[5]);
                    } else {
                        $string = "";
                    }

                    if (isset($args[7])) {
                        $type = trim($args[7]);
                    } else {
                        $type = "decimal";
                    }

                    $p = $this->_frame->lookup_counter_frame($counter_id);
                    $tmp = [];
                    while ($p) {
                        // We only want to use the counter values when they actually increment the counter
                        if (array_key_exists($counter_id, $p->_counters)) {
                            array_unshift($tmp, $p->counter_value($counter_id, $type));
                        }
                        $p = $p->lookup_counter_frame($counter_id);
                    }
                    $text .= implode($string, $tmp);
                } else {
                    // countertops?
                }

                continue;
            }
        }

        return $text;
    }

    /**
     * Handle counters and set generated content if the frame is a
     * generated-content frame.
     */
    protected function _set_content(): void
    {
        $frame = $this->_frame;

        if ($frame->content_set) {
            return;
        }

        $style = $frame->get_style();

        if (($reset = $style->counter_reset) !== "none") {
            $frame->reset_counters($reset);
        }

        if (($increment = $style->counter_increment) !== "none") {
            $frame->increment_counters($increment);
        }

        if ($frame->get_node()->nodeName === "dompdf_generated") {
            $content = $this->_parse_content();

            if ($content !== "") {
                $node = $frame->get_node()->ownerDocument->createTextNode($content);

                $new_style = $style->get_stylesheet()->create_style();
                $new_style->inherit($style);

                $new_frame = new Frame($node);
                $new_frame->set_style($new_style);

                Factory::decorate_frame($new_frame, $frame->get_dompdf(), $frame->get_root());
                $frame->append_child($new_frame);
            }
        }

        $frame->content_set = true;
    }
}
Hacker Blog, Shell İndir, Sql İnjection, XSS Attacks, LFI Attacks, Social Hacking, Exploit Bot, Proxy Tools, Web Shell, PHP Shell, Alfa Shell İndir, Hacking Training Set, DDoS Script, Denial Of Service, Botnet, RFI Attacks, Encryption
Telegram @BIBIL_0DAY