Ejemplo n.º 1
0
 protected function assertConversion($input, $expect, $unit = null, $test_negative = true)
 {
     $length = HTMLPurifier_Length::make($input);
     if ($expect !== false) {
         $expectl = HTMLPurifier_Length::make($expect);
     } else {
         $expectl = false;
     }
     $to_unit = $unit !== null ? $unit : $expectl->getUnit();
     $converter = new HTMLPurifier_UnitConverter(4, 10);
     $result = $converter->convert($length, $to_unit);
     if (!$result || !$expectl) {
         $this->assertIdentical($result, $expectl);
     } else {
         $this->assertIdentical($result->toString(), $expectl->toString());
     }
     $converter = new HTMLPurifier_UnitConverter(4, 10, true);
     $result = $converter->convert($length, $to_unit);
     if (!$result || !$expectl) {
         $this->assertIdentical($result, $expectl);
     } else {
         $this->assertIdentical($result->toString(), $expectl->toString(), 'BCMath substitute: %s');
     }
     if ($test_negative) {
         $this->assertConversion("-{$input}", $expect === false ? false : "-{$expect}", $unit, false);
     }
 }
Ejemplo n.º 2
0
 /**
  * @param $s1 First string to compare
  * @param $s2 Second string to compare
  * @param $expect 0 for $s1 == $s2, 1 for $s1 > $s2 and -1 for $s1 < $s2
  */
 protected function assertComparison($s1, $s2, $expect = 0)
 {
     $l1 = HTMLPurifier_Length::make($s1);
     $l2 = HTMLPurifier_Length::make($s2);
     $r1 = $l1->compareTo($l2);
     $r2 = $l2->compareTo($l1);
     $this->assertIdentical($r1 == 0 ? 0 : ($r1 > 0 ? 1 : -1), $expect);
     $this->assertIdentical($r2 == 0 ? 0 : ($r2 > 0 ? 1 : -1), -$expect);
 }
Ejemplo n.º 3
0
 /**
  * @param string $string
  * @param HTMLPurifier_Config $config
  * @param HTMLPurifier_Context $context
  * @return bool|string
  */
 public function validate($string, $config, $context)
 {
     $string = $this->parseCDATA($string);
     // Optimizations
     if ($string === '') {
         return false;
     }
     if ($string === '0') {
         return '0';
     }
     if (strlen($string) === 1) {
         return false;
     }
     $length = HTMLPurifier_Length::make($string);
     if (!$length->isValid()) {
         return false;
     }
     if ($this->min) {
         $c = $length->compareTo($this->min);
         if ($c === false) {
             return false;
         }
         if ($c < 0) {
             return false;
         }
     }
     if ($this->max) {
         $c = $length->compareTo($this->max);
         if ($c === false) {
             return false;
         }
         if ($c > 0) {
             return false;
         }
     }
     return $length->toString();
 }
Ejemplo n.º 4
0
 /**
  * Converts a length object of one unit into another unit.
  * @param HTMLPurifier_Length $length
  *      Instance of HTMLPurifier_Length to convert. You must validate()
  *      it before passing it here!
  * @param string $to_unit
  *      Unit to convert to.
  * @note
  *      About precision: This conversion function pays very special
  *      attention to the incoming precision of values and attempts
  *      to maintain a number of significant figure. Results are
  *      fairly accurate up to nine digits. Some caveats:
  *          - If a number is zero-padded as a result of this significant
  *            figure tracking, the zeroes will be eliminated.
  *          - If a number contains less than four sigfigs ($outputPrecision)
  *            and this causes some decimals to be excluded, those
  *            decimals will be added on.
  */
 function convert($length, $to_unit)
 {
     /**
      * Units information array. Units are grouped into measuring systems
      * (English, Metric), and are assigned an integer representing
      * the conversion factor between that unit and the smallest unit in
      * the system. Numeric indexes are actually magical constants that
      * encode conversion data from one system to the next, with a O(n^2)
      * constraint on memory (this is generally not a problem, since
      * the number of measuring systems is small.)
      */
     static $units = array(1 => array('px' => 3, 'pt' => 4, 'pc' => 48, 'in' => 288, 2 => array('pt', '0.352777778', 'mm')), 2 => array('mm' => 1, 'cm' => 10, 1 => array('mm', '2.83464567', 'pt')));
     if (!$length->isValid()) {
         return false;
     }
     $n = $length->getN();
     $unit = $length->getUnit();
     if ($n === '0' || $unit === false) {
         return new HTMLPurifier_Length('0', false);
     }
     $state = $dest_state = false;
     foreach ($units as $k => $x) {
         if (isset($x[$unit])) {
             $state = $k;
         }
         if (isset($x[$to_unit])) {
             $dest_state = $k;
         }
     }
     if (!$state || !$dest_state) {
         return false;
     }
     // Some calculations about the initial precision of the number;
     // this will be useful when we need to do final rounding.
     $sigfigs = $this->getSigFigs($n);
     if ($sigfigs < $this->outputPrecision) {
         $sigfigs = $this->outputPrecision;
     }
     // Cleanup $n for PHP 4.3.9 and 4.3.10. See http://bugs.php.net/bug.php?id=30726
     if (strncmp($n, '-.', 2) === 0) {
         $n = '-0.' . substr($n, 2);
     }
     // BCMath's internal precision deals only with decimals. Use
     // our default if the initial number has no decimals, or increase
     // it by how ever many decimals, thus, the number of guard digits
     // will always be greater than or equal to internalPrecision.
     $log = (int) floor(log(abs($n), 10));
     $cp = $log < 0 ? $this->internalPrecision - $log : $this->internalPrecision;
     // internal precision
     for ($i = 0; $i < 2; $i++) {
         // Determine what unit IN THIS SYSTEM we need to convert to
         if ($dest_state === $state) {
             // Simple conversion
             $dest_unit = $to_unit;
         } else {
             // Convert to the smallest unit, pending a system shift
             $dest_unit = $units[$state][$dest_state][0];
         }
         // Do the conversion if necessary
         if ($dest_unit !== $unit) {
             $factor = $this->div($units[$state][$unit], $units[$state][$dest_unit], $cp);
             $n = $this->mul($n, $factor, $cp);
             $unit = $dest_unit;
         }
         // Output was zero, so bail out early. Shouldn't ever happen.
         if ($n === '') {
             $n = '0';
             $unit = $to_unit;
             break;
         }
         // It was a simple conversion, so bail out
         if ($dest_state === $state) {
             break;
         }
         if ($i !== 0) {
             // Conversion failed! Apparently, the system we forwarded
             // to didn't have this unit. This should never happen!
             return false;
         }
         // Pre-condition: $i == 0
         // Perform conversion to next system of units
         $n = $this->mul($n, $units[$state][$dest_state][1], $cp);
         $unit = $units[$state][$dest_state][2];
         $state = $dest_state;
         // One more loop around to convert the unit in the new system.
     }
     // Post-condition: $unit == $to_unit
     if ($unit !== $to_unit) {
         return false;
     }
     // Useful for debugging:
     //echo "<pre>n";
     //echo "$n\nsigfigs = $sigfigs\nnew_log = $new_log\nlog = $log\nrp = $rp\n</pre>\n";
     $n = $this->round($n, $sigfigs);
     if (strpos($n, '.') !== false) {
         $n = rtrim($n, '0');
     }
     $n = rtrim($n, '.');
     return new HTMLPurifier_Length($n, $unit);
 }
Ejemplo n.º 5
0
 /**
  * Converts a length object of one unit into another unit.
  * @param HTMLPurifier_Length $length
  *      Instance of HTMLPurifier_Length to convert. You must validate()
  *      it before passing it here!
  * @param string $to_unit
  *      Unit to convert to.
  * @note
  *      About precision: This conversion function pays very special
  *      attention to the incoming precision of values and attempts
  *      to maintain a number of significant figure. Results are
  *      fairly accurate up to nine digits. Some caveats:
  *          - If a number is zero-padded as a result of this significant
  *            figure tracking, the zeroes will be eliminated.
  *          - If a number contains less than four sigfigs ($outputPrecision)
  *            and this causes some decimals to be excluded, those
  *            decimals will be added on.
  */
 public function convert($length, $to_unit)
 {
     if (!$length->isValid()) {
         return false;
     }
     $n = $length->getN();
     $unit = $length->getUnit();
     if ($n === '0' || $unit === false) {
         return new HTMLPurifier_Length('0', false);
     }
     $state = $dest_state = false;
     foreach (self::$units as $k => $x) {
         if (isset($x[$unit])) {
             $state = $k;
         }
         if (isset($x[$to_unit])) {
             $dest_state = $k;
         }
     }
     if (!$state || !$dest_state) {
         return false;
     }
     // Some calculations about the initial precision of the number;
     // this will be useful when we need to do final rounding.
     $sigfigs = $this->getSigFigs($n);
     if ($sigfigs < $this->outputPrecision) {
         $sigfigs = $this->outputPrecision;
     }
     // BCMath's internal precision deals only with decimals. Use
     // our default if the initial number has no decimals, or increase
     // it by how ever many decimals, thus, the number of guard digits
     // will always be greater than or equal to internalPrecision.
     $log = (int) floor(log(abs($n), 10));
     $cp = $log < 0 ? $this->internalPrecision - $log : $this->internalPrecision;
     // internal precision
     for ($i = 0; $i < 2; $i++) {
         // Determine what unit IN THIS SYSTEM we need to convert to
         if ($dest_state === $state) {
             // Simple conversion
             $dest_unit = $to_unit;
         } else {
             // Convert to the smallest unit, pending a system shift
             $dest_unit = self::$units[$state][$dest_state][0];
         }
         // Do the conversion if necessary
         if ($dest_unit !== $unit) {
             $factor = $this->div(self::$units[$state][$unit], self::$units[$state][$dest_unit], $cp);
             $n = $this->mul($n, $factor, $cp);
             $unit = $dest_unit;
         }
         // Output was zero, so bail out early. Shouldn't ever happen.
         if ($n === '') {
             $n = '0';
             $unit = $to_unit;
             break;
         }
         // It was a simple conversion, so bail out
         if ($dest_state === $state) {
             break;
         }
         if ($i !== 0) {
             // Conversion failed! Apparently, the system we forwarded
             // to didn't have this unit. This should never happen!
             return false;
         }
         // Pre-condition: $i == 0
         // Perform conversion to next system of units
         $n = $this->mul($n, self::$units[$state][$dest_state][1], $cp);
         $unit = self::$units[$state][$dest_state][2];
         $state = $dest_state;
         // One more loop around to convert the unit in the new system.
     }
     // Post-condition: $unit == $to_unit
     if ($unit !== $to_unit) {
         return false;
     }
     // Useful for debugging:
     //echo "<pre>n";
     //echo "$n\nsigfigs = $sigfigs\nnew_log = $new_log\nlog = $log\nrp = $rp\n</pre>\n";
     $n = $this->round($n, $sigfigs);
     if (strpos($n, '.') !== false) {
         $n = rtrim($n, '0');
     }
     $n = rtrim($n, '.');
     return new HTMLPurifier_Length($n, $unit);
 }