[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/phpseclib/phpseclib/phpseclib/Common/Functions/ -> Strings.php (source)

   1  <?php
   2  
   3  /**
   4   * Common String Functions
   5   *
   6   * PHP version 5
   7   *
   8   * @category  Common
   9   * @package   Functions\Strings
  10   * @author    Jim Wigginton <[email protected]>
  11   * @copyright 2016 Jim Wigginton
  12   * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  13   * @link      http://phpseclib.sourceforge.net
  14   */
  15  
  16  namespace phpseclib3\Common\Functions;
  17  
  18  use phpseclib3\Math\BigInteger;
  19  use phpseclib3\Math\Common\FiniteField;
  20  
  21  /**
  22   * Common String Functions
  23   *
  24   * @package Functions\Strings
  25   * @author  Jim Wigginton <[email protected]>
  26   */
  27  abstract class Strings
  28  {
  29      /**
  30       * String Shift
  31       *
  32       * Inspired by array_shift
  33       *
  34       * @param string $string
  35       * @param int $index
  36       * @access public
  37       * @return string
  38       */
  39      public static function shift(&$string, $index = 1)
  40      {
  41          $substr = substr($string, 0, $index);
  42          $string = substr($string, $index);
  43          return $substr;
  44      }
  45  
  46      /**
  47       * String Pop
  48       *
  49       * Inspired by array_pop
  50       *
  51       * @param string $string
  52       * @param int $index
  53       * @access public
  54       * @return string
  55       */
  56      public static function pop(&$string, $index = 1)
  57      {
  58          $substr = substr($string, -$index);
  59          $string = substr($string, 0, -$index);
  60          return $substr;
  61      }
  62  
  63      /**
  64       * Parse SSH2-style string
  65       *
  66       * Returns either an array or a boolean if $data is malformed.
  67       *
  68       * Valid characters for $format are as follows:
  69       *
  70       * C = byte
  71       * b = boolean (true/false)
  72       * N = uint32
  73       * Q = uint64
  74       * s = string
  75       * i = mpint
  76       * L = name-list
  77       *
  78       * uint64 is not supported.
  79       *
  80       * @param string $format
  81       * @param string $data
  82       * @return mixed
  83       */
  84      public static function unpackSSH2($format, &$data)
  85      {
  86          $format = self::formatPack($format);
  87          $result = [];
  88          for ($i = 0; $i < strlen($format); $i++) {
  89              switch ($format[$i]) {
  90                  case 'C':
  91                  case 'b':
  92                      if (!strlen($data)) {
  93                          throw new \LengthException('At least one byte needs to be present for successful C / b decodes');
  94                      }
  95                      break;
  96                  case 'N':
  97                  case 'i':
  98                  case 's':
  99                  case 'L':
 100                      if (strlen($data) < 4) {
 101                          throw new \LengthException('At least four byte needs to be present for successful N / i / s / L decodes');
 102                      }
 103                      break;
 104                  case 'Q':
 105                      if (strlen($data) < 8) {
 106                          throw new \LengthException('At least eight byte needs to be present for successful N / i / s / L decodes');
 107                      }
 108                      break;
 109  
 110                  default:
 111                      throw new \InvalidArgumentException('$format contains an invalid character');
 112              }
 113              switch ($format[$i]) {
 114                  case 'C':
 115                      $result[] = ord(self::shift($data));
 116                      continue 2;
 117                  case 'b':
 118                      $result[] = ord(self::shift($data)) != 0;
 119                      continue 2;
 120                  case 'N':
 121                      list(, $temp) = unpack('N', self::shift($data, 4));
 122                      $result[] = $temp;
 123                      continue 2;
 124                  case 'Q':
 125                      // pack() added support for Q in PHP 5.6.3 and PHP 5.6 is phpseclib 3's minimum version
 126                      // so in theory we could support this BUT, "64-bit format codes are not available for
 127                      // 32-bit versions" and phpseclib works on 32-bit installs. on 32-bit installs
 128                      // 64-bit floats can be used to get larger numbers then 32-bit signed ints would allow
 129                      // for. sure, you're not gonna get the full precision of 64-bit numbers but just because
 130                      // you need > 32-bit precision doesn't mean you need the full 64-bit precision
 131                      extract(unpack('Nupper/Nlower', self::shift($data, 8)));
 132                      $temp = $upper ? 4294967296 * $upper : 0;
 133                      $temp += $lower < 0 ? ($lower & 0x7FFFFFFFF) + 0x80000000 : $lower;
 134                      // $temp = hexdec(bin2hex(self::shift($data, 8)));
 135                      $result[] = $temp;
 136                      continue 2;
 137              }
 138              list(, $length) = unpack('N', self::shift($data, 4));
 139              if (strlen($data) < $length) {
 140                  throw new \LengthException("$length bytes needed; " . strlen($data) . ' bytes available');
 141              }
 142              $temp = self::shift($data, $length);
 143              switch ($format[$i]) {
 144                  case 'i':
 145                      $result[] = new BigInteger($temp, -256);
 146                      break;
 147                  case 's':
 148                      $result[] = $temp;
 149                      break;
 150                  case 'L':
 151                      $result[] = explode(',', $temp);
 152              }
 153          }
 154  
 155          return $result;
 156      }
 157  
 158      /**
 159       * Create SSH2-style string
 160       *
 161       * @param string $format
 162       * @param string|int|float|array|bool ...$elements
 163       * @access public
 164       * @return string
 165       */
 166      public static function packSSH2($format, ...$elements)
 167      {
 168          $format = self::formatPack($format);
 169          if (strlen($format) != count($elements)) {
 170              throw new \InvalidArgumentException('There must be as many arguments as there are characters in the $format string');
 171          }
 172          $result = '';
 173          for ($i = 0; $i < strlen($format); $i++) {
 174              $element = $elements[$i];
 175              switch ($format[$i]) {
 176                  case 'C':
 177                      if (!is_int($element)) {
 178                          throw new \InvalidArgumentException('Bytes must be represented as an integer between 0 and 255, inclusive.');
 179                      }
 180                      $result .= pack('C', $element);
 181                      break;
 182                  case 'b':
 183                      if (!is_bool($element)) {
 184                          throw new \InvalidArgumentException('A boolean parameter was expected.');
 185                      }
 186                      $result .= $element ? "\1" : "\0";
 187                      break;
 188                  case 'Q':
 189                      if (!is_int($element) && !is_float($element)) {
 190                          throw new \InvalidArgumentException('An integer was expected.');
 191                      }
 192                      // 4294967296 == 1 << 32
 193                      $result .= pack('NN', $element / 4294967296, $element);
 194                      break;
 195                  case 'N':
 196                      if (is_float($element)) {
 197                          $element = (int) $element;
 198                      }
 199                      if (!is_int($element)) {
 200                          throw new \InvalidArgumentException('An integer was expected.');
 201                      }
 202                      $result .= pack('N', $element);
 203                      break;
 204                  case 's':
 205                      if (!self::is_stringable($element)) {
 206                          throw new \InvalidArgumentException('A string was expected.');
 207                      }
 208                      $result .= pack('Na*', strlen($element), $element);
 209                      break;
 210                  case 'i':
 211                      if (!$element instanceof BigInteger && !$element instanceof FiniteField\Integer) {
 212                          throw new \InvalidArgumentException('A phpseclib3\Math\BigInteger or phpseclib3\Math\Common\FiniteField\Integer object was expected.');
 213                      }
 214                      $element = $element->toBytes(true);
 215                      $result .= pack('Na*', strlen($element), $element);
 216                      break;
 217                  case 'L':
 218                      if (!is_array($element)) {
 219                          throw new \InvalidArgumentException('An array was expected.');
 220                      }
 221                      $element = implode(',', $element);
 222                      $result .= pack('Na*', strlen($element), $element);
 223                      break;
 224                  default:
 225                      throw new \InvalidArgumentException('$format contains an invalid character');
 226              }
 227          }
 228          return $result;
 229      }
 230  
 231      /**
 232       * Expand a pack string
 233       *
 234       * Converts C5 to CCCCC, for example.
 235       *
 236       * @access private
 237       * @param string $format
 238       * @return string
 239       */
 240      private static function formatPack($format)
 241      {
 242          $parts = preg_split('#(\d+)#', $format, -1, PREG_SPLIT_DELIM_CAPTURE);
 243          $format = '';
 244          for ($i = 1; $i < count($parts); $i += 2) {
 245              $format .= substr($parts[$i - 1], 0, -1) . str_repeat(substr($parts[$i - 1], -1), $parts[$i]);
 246          }
 247          $format .= $parts[$i - 1];
 248  
 249          return $format;
 250      }
 251  
 252      /**
 253       * Convert binary data into bits
 254       *
 255       * bin2hex / hex2bin refer to base-256 encoded data as binary, whilst
 256       * decbin / bindec refer to base-2 encoded data as binary. For the purposes
 257       * of this function, bin refers to base-256 encoded data whilst bits refers
 258       * to base-2 encoded data
 259       *
 260       * @access public
 261       * @param string $x
 262       * @return string
 263       */
 264      public static function bits2bin($x)
 265      {
 266          /*
 267          // the pure-PHP approach is faster than the GMP approach
 268          if (function_exists('gmp_export')) {
 269               return strlen($x) ? gmp_export(gmp_init($x, 2)) : gmp_init(0);
 270          }
 271          */
 272  
 273          if (preg_match('#[^01]#', $x)) {
 274              throw new \RuntimeException('The only valid characters are 0 and 1');
 275          }
 276  
 277          if (!defined('PHP_INT_MIN')) {
 278              define('PHP_INT_MIN', ~PHP_INT_MAX);
 279          }
 280  
 281          $length = strlen($x);
 282          if (!$length) {
 283              return '';
 284          }
 285          $block_size = PHP_INT_SIZE << 3;
 286          $pad = $block_size - ($length % $block_size);
 287          if ($pad != $block_size) {
 288              $x = str_repeat('0', $pad) . $x;
 289          }
 290  
 291          $parts = str_split($x, $block_size);
 292          $str = '';
 293          foreach ($parts as $part) {
 294              $xor = $part[0] == '1' ? PHP_INT_MIN : 0;
 295              $part[0] = '0';
 296              $str .= pack(
 297                  PHP_INT_SIZE == 4 ? 'N' : 'J',
 298                  $xor ^ eval('return 0b' . $part . ';')
 299              );
 300          }
 301          return ltrim($str, "\0");
 302      }
 303  
 304      /**
 305       * Convert bits to binary data
 306       *
 307       * @access public
 308       * @param string $x
 309       * @return string
 310       */
 311      public static function bin2bits($x, $trim = true)
 312      {
 313          /*
 314          // the pure-PHP approach is slower than the GMP approach BUT
 315          // i want to the pure-PHP version to be easily unit tested as well
 316          if (function_exists('gmp_import')) {
 317              return gmp_strval(gmp_import($x), 2);
 318          }
 319          */
 320  
 321          $len = strlen($x);
 322          $mod = $len % PHP_INT_SIZE;
 323          if ($mod) {
 324              $x = str_pad($x, $len + PHP_INT_SIZE - $mod, "\0", STR_PAD_LEFT);
 325          }
 326  
 327          $bits = '';
 328          if (PHP_INT_SIZE == 4) {
 329              $digits = unpack('N*', $x);
 330              foreach ($digits as $digit) {
 331                  $bits .= sprintf('%032b', $digit);
 332              }
 333          } else {
 334              $digits = unpack('J*', $x);
 335              foreach ($digits as $digit) {
 336                  $bits .= sprintf('%064b', $digit);
 337              }
 338          }
 339  
 340          return $trim ? ltrim($bits, '0') : $bits;
 341      }
 342  
 343      /**
 344       * Switch Endianness Bit Order
 345       *
 346       * @access public
 347       * @param string $x
 348       * @return string
 349       */
 350      public static function switchEndianness($x)
 351      {
 352          $r = '';
 353          for ($i = strlen($x) - 1; $i >= 0; $i--) {
 354              $b = ord($x[$i]);
 355              if (PHP_INT_SIZE === 8) {
 356                  // 3 operations
 357                  // from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64BitsDiv
 358                  $r .= chr((($b * 0x0202020202) & 0x010884422010) % 1023);
 359              } else {
 360                  // 7 operations
 361                  // from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits
 362                  $p1 = ($b * 0x0802) & 0x22110;
 363                  $p2 = ($b * 0x8020) & 0x88440;
 364                  $r .= chr(
 365                      (($p1 | $p2) * 0x10101) >> 16
 366                  );
 367              }
 368          }
 369          return $r;
 370      }
 371  
 372      /**
 373       * Increment the current string
 374       *
 375       * @param string $var
 376       * @return string
 377       * @access public
 378       */
 379      public static function increment_str(&$var)
 380      {
 381          if (function_exists('sodium_increment')) {
 382              $var = strrev($var);
 383              sodium_increment($var);
 384              $var = strrev($var);
 385              return $var;
 386          }
 387  
 388          for ($i = 4; $i <= strlen($var); $i += 4) {
 389              $temp = substr($var, -$i, 4);
 390              switch ($temp) {
 391                  case "\xFF\xFF\xFF\xFF":
 392                      $var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
 393                      break;
 394                  case "\x7F\xFF\xFF\xFF":
 395                      $var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
 396                      return $var;
 397                  default:
 398                      $temp = unpack('Nnum', $temp);
 399                      $var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
 400                      return $var;
 401              }
 402          }
 403  
 404          $remainder = strlen($var) % 4;
 405  
 406          if ($remainder == 0) {
 407              return $var;
 408          }
 409  
 410          $temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT));
 411          $temp = substr(pack('N', $temp['num'] + 1), -$remainder);
 412          $var = substr_replace($var, $temp, 0, $remainder);
 413  
 414          return $var;
 415      }
 416  
 417      /**
 418       * Find whether the type of a variable is string (or could be converted to one)
 419       *
 420       * @param mixed $var
 421       * @return bool
 422       * @psalm-assert-if-true string|\Stringable $var
 423       */
 424      public static function is_stringable($var)
 425      {
 426          return is_string($var) || (is_object($var) && method_exists($var, '__toString'));
 427      }
 428  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer