Uname: Linux webm005.cluster107.gra.hosting.ovh.net 5.15.167-ovh-vps-grsec-zfs-classid #1 SMP Tue Sep 17 08:14:20 UTC 2024 x86_64
User: 6036 (villadal)
Group: 100 (users)
Disabled functions: NONE
Safe mode: On[ PHPinfo ]
//home/villadal/www///////wp-includes      ( Reset | Go to )
File Name: class-avif-info.php
Edit
<?php
/**
 * Copyright (c) 2021, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 *
 * Note: this class is from libavifinfo - https://aomedia.googlesource.com/libavifinfo/+/refs/heads/main/avifinfo.php at f509487.
 * It is used as a fallback to parse AVIF files when the server doesn't support AVIF,
 * primarily to identify the width and height of the image.
 *
 * Note PHP 8.2 added native support for AVIF, so this class can be removed when WordPress requires PHP 8.2.
 */

namespace Avifinfo;

const 
FOUND     0// Input correctly parsed and information retrieved.
const NOT_FOUND 1// Input correctly parsed but information is missing or elsewhere.
const TRUNCATED 2// Input correctly parsed until missing bytes to continue.
const ABORTED   3// Input correctly parsed until stopped to avoid timeout or crash.
const INVALID   4// Input incorrectly parsed.

const MAX_SIZE      4294967295// Unlikely to be insufficient to parse AVIF headers.
const MAX_NUM_BOXES 4096;       // Be reasonable. Avoid timeouts and out-of-memory.
const MAX_VALUE     255;
const 
MAX_TILES     16;
const 
MAX_PROPS     32;
const 
MAX_FEATURES  8;
const 
UNDEFINED     0;          // Value was not yet parsed.

/**
 * Reads an unsigned integer with most significant bits first.
 *
 * @param binary string $input     Must be at least $num_bytes-long.
 * @param int           $num_bytes Number of parsed bytes.
 * @return int                     Value.
 */
function read_big_endian$input$num_bytes ) {
  if ( 
$num_bytes == ) {
    return 
unpack'C'$input ) [1];
  } else if ( 
$num_bytes == ) {
    return 
unpack'n'$input ) [1];
  } else if ( 
$num_bytes == ) {
    
$bytes unpack'C3'$input );
    return ( 
$bytes[1] << 16 ) | ( $bytes[2] << ) | $bytes[3];
  } else { 
// $num_bytes is 4
    // This might fail to read unsigned values >= 2^31 on 32-bit systems.
    // See https://www.php.net/manual/en/function.unpack.php#106041
    
return unpack'N'$input ) [1];
  }
}

/**
 * Reads bytes and advances the stream position by the same count.
 *
 * @param stream               $handle    Bytes will be read from this resource.
 * @param int                  $num_bytes Number of bytes read. Must be greater than 0.
 * @return binary string|false            The raw bytes or false on failure.
 */
function read$handle$num_bytes ) {
  
$data fread$handle$num_bytes );
  return ( 
$data !== false && strlen$data ) >= $num_bytes ) ? $data false;
}

/**
 * Advances the stream position by the given offset.
 *
 * @param stream $handle    Bytes will be skipped from this resource.
 * @param int    $num_bytes Number of skipped bytes. Can be 0.
 * @return bool             True on success or false on failure.
 */
// Skips 'num_bytes' from the 'stream'. 'num_bytes' can be zero.
function skip$handle$num_bytes ) {
  return ( 
fseek$handle$num_bytesSEEK_CUR ) == );
}

//------------------------------------------------------------------------------
// Features are parsed into temporary property associations.

class Tile // Tile item id <-> parent item id associations.
  
public $tile_item_id;
  public 
$parent_item_id;
}

class 
Prop // Property index <-> item id associations.
  
public $property_index;
  public 
$item_id;
}

class 
Dim_Prop // Property <-> features associations.
  
public $property_index;
  public 
$width;
  public 
$height;
}

class 
Chan_Prop // Property <-> features associations.
  
public $property_index;
  public 
$bit_depth;
  public 
$num_channels;
}

class 
Features {
  public 
$has_primary_item false// True if "pitm" was parsed.
  
public $has_alpha false// True if an alpha "auxC" was parsed.
  
public $primary_item_id;
  public 
$primary_item_features = array( // Deduced from the data below.
    
'width'        => UNDEFINED// In number of pixels.
    
'height'       => UNDEFINED// Ignores mirror and rotation.
    
'bit_depth'    => UNDEFINED// Likely 8, 10 or 12 bits per channel per pixel.
    
'num_channels' => UNDEFINED  // Likely 1, 2, 3 or 4 channels:
                                          //   (1 monochrome or 3 colors) + (0 or 1 alpha)
  
);

  public 
$tiles = array(); // Tile[]
  
public $props = array(); // Prop[]
  
public $dim_props = array(); // Dim_Prop[]
  
public $chan_props = array(); // Chan_Prop[]

  /**
   * Binds the width, height, bit depth and number of channels from stored internal features.
   *
   * @param int     $target_item_id Id of the item whose features will be bound.
   * @param int     $tile_depth     Maximum recursion to search within tile-parent relations.
   * @return Status                 FOUND on success or NOT_FOUND on failure.
   */
  
private function get_item_features$target_item_id$tile_depth ) {
    foreach ( 
$this->props as $prop ) {
      if ( 
$prop->item_id != $target_item_id ) {
        continue;
      }

      
// Retrieve the width and height of the primary item if not already done.
      
if ( $target_item_id == $this->primary_item_id &&
           ( 
$this->primary_item_features['width'] == UNDEFINED ||
             
$this->primary_item_features['height'] == UNDEFINED ) ) {
        foreach ( 
$this->dim_props as $dim_prop ) {
          if ( 
$dim_prop->property_index != $prop->property_index ) {
            continue;
          }
          
$this->primary_item_features['width']  = $dim_prop->width;
          
$this->primary_item_features['height'] = $dim_prop->height;
          if ( 
$this->primary_item_features['bit_depth'] != UNDEFINED &&
               
$this->primary_item_features['num_channels'] != UNDEFINED ) {
            return 
FOUND;
          }
          break;
        }
      }
      
// Retrieve the bit depth and number of channels of the target item if not
      // already done.
      
if ( $this->primary_item_features['bit_depth'] == UNDEFINED ||
           
$this->primary_item_features['num_channels'] == UNDEFINED ) {
        foreach ( 
$this->chan_props as $chan_prop ) {
          if ( 
$chan_prop->property_index != $prop->property_index ) {
            continue;
          }
          
$this->primary_item_features['bit_depth']    = $chan_prop->bit_depth;
          
$this->primary_item_features['num_channels'] = $chan_prop->num_channels;
          if ( 
$this->primary_item_features['width'] != UNDEFINED &&
              
$this->primary_item_features['height'] != UNDEFINED ) {
            return 
FOUND;
          }
          break;
        }
      }
    }

    
// Check for the bit_depth and num_channels in a tile if not yet found.
    
if ( $tile_depth ) {
      foreach ( 
$this->tiles as $tile ) {
        if ( 
$tile->parent_item_id != $target_item_id ) {
          continue;
        }
        
$status $this->get_item_features$tile->tile_item_id$tile_depth );
        if ( 
$status != NOT_FOUND ) {
          return 
$status;
        }
      }
    }
    return 
NOT_FOUND;
  }

  
/**
   * Finds the width, height, bit depth and number of channels of the primary item.
   *
   * @return Status FOUND on success or NOT_FOUND on failure.
   */
  
public function get_primary_item_features() {
    
// Nothing to do without the primary item ID.
    
if ( !$this->has_primary_item ) {
      return 
NOT_FOUND;
    }
    
// Early exit.
    
if ( empty( $this->dim_props ) || empty( $this->chan_props ) ) {
      return 
NOT_FOUND;
    }
    
$status $this->get_item_features$this->primary_item_id/*tile_depth=*/ );
    if ( 
$status != FOUND ) {
      return 
$status;
    }

    
// "auxC" is parsed before the "ipma" properties so it is known now, if any.
    
if ( $this->has_alpha ) {
      ++
$this->primary_item_features['num_channels'];
    }
    return 
FOUND;
  }
}

//------------------------------------------------------------------------------

class Box {
  public 
$size// In bytes.
  
public $type// Four characters.
  
public $version// 0 or actual version if this is a full box.
  
public $flags// 0 or actual value if this is a full box.
  
public $content_size// 'size' minus the header size.

  /**
   * Reads the box header.
   *
   * @param stream  $handle              The resource the header will be parsed from.
   * @param int     $num_parsed_boxes    The total number of parsed boxes. Prevents timeouts.
   * @param int     $num_remaining_bytes The number of bytes that should be available from the resource.
   * @return Status                      FOUND on success or an error on failure.
   */
  
public function parse$handle, &$num_parsed_boxes$num_remaining_bytes MAX_SIZE ) {
    
// See ISO/IEC 14496-12:2012(E) 4.2
    
$header_size 8// box 32b size + 32b type (at least)
    
if ( $header_size $num_remaining_bytes ) {
      return 
INVALID;
    }
    if ( !( 
$data read$handle) ) ) {
      return 
TRUNCATED;
    }
    
$this->size read_big_endian$data);
    
$this->type substr$data4);
    
// 'box->size==1' means 64-bit size should be read after the box type.
    // 'box->size==0' means this box extends to all remaining bytes.
    
if ( $this->size == ) {
      
$header_size += 8;
      if ( 
$header_size $num_remaining_bytes ) {
        return 
INVALID;
      }
      if ( !( 
$data read$handle) ) ) {
        return 
TRUNCATED;
      }
      
// Stop the parsing if any box has a size greater than 4GB.
      
if ( read_big_endian$data) != ) {
        return 
ABORTED;
      }
      
// Read the 32 least-significant bits.
      
$this->size read_big_endiansubstr$data4), );
    } else if ( 
$this->size == ) {
      
$this->size $num_remaining_bytes;
    }
    if ( 
$this->size $header_size ) {
      return 
INVALID;
    }
    if ( 
$this->size $num_remaining_bytes ) {
      return 
INVALID;
    }

    
$has_fullbox_header $this->type == 'meta' || $this->type == 'pitm' ||
                          
$this->type == 'ipma' || $this->type == 'ispe' ||
                          
$this->type == 'pixi' || $this->type == 'iref' ||
                          
$this->type == 'auxC';
    if ( 
$has_fullbox_header ) {
      
$header_size += 4;
    }
    if ( 
$this->size $header_size ) {
      return 
INVALID;
    }
    
$this->content_size $this->size $header_size;
    
// Avoid timeouts. The maximum number of parsed boxes is arbitrary.
    
++$num_parsed_boxes;
    if ( 
$num_parsed_boxes >= MAX_NUM_BOXES ) {
      return 
ABORTED;
    }

    
$this->version 0;
    
$this->flags   0;
    if ( 
$has_fullbox_header ) {
      if ( !( 
$data read$handle) ) ) {
        return 
TRUNCATED;
      }
      
$this->version read_big_endian$data);
      
$this->flags   read_big_endiansubstr$data1), );
      
// See AV1 Image File Format (AVIF) 8.1
      // at https://aomediacodec.github.io/av1-avif/#avif-boxes (available when
      // https://github.com/AOMediaCodec/av1-avif/pull/170 is merged).
      
$is_parsable = ( $this->type == 'meta' && $this->version <= ) ||
                     ( 
$this->type == 'pitm' && $this->version <= ) ||
                     ( 
$this->type == 'ipma' && $this->version <= ) ||
                     ( 
$this->type == 'ispe' && $this->version <= ) ||
                     ( 
$this->type == 'pixi' && $this->version <= ) ||
                     ( 
$this->type == 'iref' && $this->version <= ) ||
                     ( 
$this->type == 'auxC' && $this->version <= );
      
// Instead of considering this file as invalid, skip unparsable boxes.
      
if ( !$is_parsable ) {
        
$this->type 'unknownversion';
      }
    }
    
// print_r( $this ); // Uncomment to print all boxes.
    
return FOUND;
  }
}

//------------------------------------------------------------------------------

class Parser {
  private 
$handle// Input stream.
  
private $num_parsed_boxes 0;
  private 
$data_was_skipped false;
  public 
$features;

  function 
__construct$handle ) {
    
$this->handle   $handle;
    
$this->features = new Features();
  }

  
/**
   * Parses an "ipco" box.
   *
   * "ispe" is used for width and height, "pixi" and "av1C" are used for bit depth
   * and number of channels, and "auxC" is used for alpha.
   *
   * @param stream  $handle              The resource the box will be parsed from.
   * @param int     $num_remaining_bytes The number of bytes that should be available from the resource.
   * @return Status                      FOUND on success or an error on failure.
   */
  
private function parse_ipco$num_remaining_bytes ) {
    
$box_index 1// 1-based index. Used for iterating over properties.
    
do {
      
$box    = new Box();
      
$status $box->parse$this->handle$this->num_parsed_boxes$num_remaining_bytes );
      if ( 
$status != FOUND ) {
        return 
$status;
      }

      if ( 
$box->type == 'ispe' ) {
        
// See ISO/IEC 23008-12:2017(E) 6.5.3.2
        
if ( $box->content_size ) {
          return 
INVALID;
        }
        if ( !( 
$data read$this->handle) ) ) {
          return 
TRUNCATED;
        }
        
$width  read_big_endiansubstr$data0), );
        
$height read_big_endiansubstr$data4), );
        if ( 
$width == || $height == ) {
          return 
INVALID;
        }
        if ( 
count$this->features->dim_props ) <= MAX_FEATURES &&
             
$box_index <= MAX_VALUE ) {
          
$dim_prop_count count$this->features->dim_props );
          
$this->features->dim_props[$dim_prop_count]                 = new Dim_Prop();
          
$this->features->dim_props[$dim_prop_count]->property_index $box_index;
          
$this->features->dim_props[$dim_prop_count]->width          $width;
          
$this->features->dim_props[$dim_prop_count]->height         $height;
        } else {
          
$this->data_was_skipped true;
        }
        if ( !
skip$this->handle$box->content_size ) ) {
          return 
TRUNCATED;
        }
      } else if ( 
$box->type == 'pixi' ) {
        
// See ISO/IEC 23008-12:2017(E) 6.5.6.2
        
if ( $box->content_size ) {
          return 
INVALID;
        }
        if ( !( 
$data read$this->handle) ) ) {
          return 
TRUNCATED;
        }
        
$num_channels read_big_endian$data);
        if ( 
$num_channels ) {
          return 
INVALID;
        }
        if ( 
$box->content_size $num_channels ) {
          return 
INVALID;
        }
        if ( !( 
$data read$this->handle) ) ) {
          return 
TRUNCATED;
        }
        
$bit_depth read_big_endian$data);
        if ( 
$bit_depth ) {
          return 
INVALID;
        }
        for ( 
$i 1$i $num_channels; ++$i ) {
          if ( !( 
$data read$this->handle) ) ) {
            return 
TRUNCATED;
          }
          
// Bit depth should be the same for all channels.
          
if ( read_big_endian$data) != $bit_depth ) {
            return 
INVALID;
          }
          if ( 
$i 32 ) {
            return 
ABORTED// Be reasonable.
          
}
        }
        if ( 
count$this->features->chan_props ) <= MAX_FEATURES &&
             
$box_index <= MAX_VALUE && $bit_depth <= MAX_VALUE &&
             
$num_channels <= MAX_VALUE ) {
          
$chan_prop_count count$this->features->chan_props );
          
$this->features->chan_props[$chan_prop_count]                 = new Chan_Prop();
          
$this->features->chan_props[$chan_prop_count]->property_index $box_index;
          
$this->features->chan_props[$chan_prop_count]->bit_depth      $bit_depth;
          
$this->features->chan_props[$chan_prop_count]->num_channels   $num_channels;
        } else {
          
$this->data_was_skipped true;
        }
        if ( !
skip$this->handle$box->content_size - ( $num_channels ) ) ) {
          return 
TRUNCATED;
        }
      } else if ( 
$box->type == 'av1C' ) {
        
// See AV1 Codec ISO Media File Format Binding 2.3.1
        // at https://aomediacodec.github.io/av1-isobmff/#av1c
        // Only parse the necessary third byte. Assume that the others are valid.
        
if ( $box->content_size ) {
          return 
INVALID;
        }
        if ( !( 
$data read$this->handle) ) ) {
          return 
TRUNCATED;
        }
        
$byte          read_big_endiansubstr$data2), );
        
$high_bitdepth = ( $byte 0x40 ) != 0;
        
$twelve_bit    = ( $byte 0x20 ) != 0;
        
$monochrome    = ( $byte 0x10 ) != 0;
        if ( 
$twelve_bit && !$high_bitdepth ) {
            return 
INVALID;
        }
        if ( 
count$this->features->chan_props ) <= MAX_FEATURES &&
             
$box_index <= MAX_VALUE ) {
          
$chan_prop_count count$this->features->chan_props );
          
$this->features->chan_props[$chan_prop_count]                 = new Chan_Prop();
          
$this->features->chan_props[$chan_prop_count]->property_index $box_index;
          
$this->features->chan_props[$chan_prop_count]->bit_depth      =
              
$high_bitdepth $twelve_bit 12 10 8;
          
$this->features->chan_props[$chan_prop_count]->num_channels   $monochrome 3;
        } else {
          
$this->data_was_skipped true;
        }
        if ( !
skip$this->handle$box->content_size ) ) {
          return 
TRUNCATED;
        }
      } else if ( 
$box->type == 'auxC' ) {
        
// See AV1 Image File Format (AVIF) 4
        // at https://aomediacodec.github.io/av1-avif/#auxiliary-images
        
$kAlphaStr       "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha\0";
        
$kAlphaStrLength 44// Includes terminating character.
        
if ( $box->content_size >= $kAlphaStrLength ) {
          if ( !( 
$data read$this->handle$kAlphaStrLength ) ) ) {
            return 
TRUNCATED;
          }
          if ( 
substr$data0$kAlphaStrLength ) == $kAlphaStr ) {
            
// Note: It is unlikely but it is possible that this alpha plane does
            //       not belong to the primary item or a tile. Ignore this issue.
            
$this->features->has_alpha true;
          }
          if ( !
skip$this->handle$box->content_size $kAlphaStrLength ) ) {
            return 
TRUNCATED;
          }
        } else {
          if ( !
skip$this->handle$box->content_size ) ) {
            return 
TRUNCATED;
          }
        }
      } else {
        if ( !
skip$this->handle$box->content_size ) ) {
          return 
TRUNCATED;
        }
      }
      ++
$box_index;
      
$num_remaining_bytes -= $box->size;
    } while ( 
$num_remaining_bytes );
    return 
NOT_FOUND;
  }

  
/**
   * Parses an "iprp" box.
   *
   * The "ipco" box contain the properties which are linked to items by the "ipma" box.
   *
   * @param stream  $handle              The resource the box will be parsed from.
   * @param int     $num_remaining_bytes The number of bytes that should be available from the resource.
   * @return Status                      FOUND on success or an error on failure.
   */
  
private function parse_iprp$num_remaining_bytes ) {
    do {
      
$box    = new Box();
      
$status $box->parse$this->handle$this->num_parsed_boxes$num_remaining_bytes );
      if ( 
$status != FOUND ) {
        return 
$status;
      }

      if ( 
$box->type == 'ipco' ) {
        
$status $this->parse_ipco$box->content_size );
        if ( 
$status != NOT_FOUND ) {
          return 
$status;
        }
      } else if ( 
$box->type == 'ipma' ) {
        
// See ISO/IEC 23008-12:2017(E) 9.3.2
        
$num_read_bytes 4;
        if ( 
$box->content_size $num_read_bytes ) {
          return 
INVALID;
        }
        if ( !( 
$data read$this->handle$num_read_bytes ) ) ) {
          return 
TRUNCATED;
        }
        
$entry_count        read_big_endian$data);
        
$id_num_bytes       = ( $box->version ) ? 4;
        
$index_num_bytes    = ( $box->flags ) ? 1;
        
$essential_bit_mask = ( $box->flags ) ? 0x8000 0x80;

        for ( 
$entry 0$entry $entry_count; ++$entry ) {
          if ( 
$entry >= MAX_PROPS ||
               
count$this->features->props ) >= MAX_PROPS ) {
            
$this->data_was_skipped true;
            break;
          }
          
$num_read_bytes += $id_num_bytes 1;
          if ( 
$box->content_size $num_read_bytes ) {
            return 
INVALID;
          }
          if ( !( 
$data read$this->handle$id_num_bytes ) ) ) {
            return 
TRUNCATED;
          }
          
$item_id           read_big_endian(
              
substr$data0$id_num_bytes ), $id_num_bytes );
          
$association_count read_big_endian(
              
substr$data$id_num_bytes), );

          for ( 
$property 0$property $association_count; ++$property ) {
            if ( 
$property >= MAX_PROPS ||
                 
count$this->features->props ) >= MAX_PROPS ) {
              
$this->data_was_skipped true;
              break;
            }
            
$num_read_bytes += $index_num_bytes;
            if ( 
$box->content_size $num_read_bytes ) {
              return 
INVALID;
            }
            if ( !( 
$data read$this->handle$index_num_bytes ) ) ) {
              return 
TRUNCATED;
            }
            
$value          read_big_endian$data$index_num_bytes );
            
// $essential = ($value & $essential_bit_mask);  // Unused.
            
$property_index = ( $value & ~$essential_bit_mask );
            if ( 
$property_index <= MAX_VALUE && $item_id <= MAX_VALUE ) {
              
$prop_count count$this->features->props );
              
$this->features->props[$prop_count]                 = new Prop();
              
$this->features->props[$prop_count]->property_index $property_index;
              
$this->features->props[$prop_count]->item_id        $item_id;
            } else {
              
$this->data_was_skipped true;
            }
          }
          if ( 
$property $association_count ) {
            break; 
// Do not read garbage.
          
}
        }

        
// If all features are available now, do not look further.
        
$status $this->features->get_primary_item_features();
        if ( 
$status != NOT_FOUND ) {
          return 
$status;
        }

        
// Mostly if 'data_was_skipped'.
        
if ( !skip$this->handle$box->content_size $num_read_bytes ) ) {
          return 
TRUNCATED;
        }
      } else {
        if ( !
skip$this->handle$box->content_size ) ) {
          return 
TRUNCATED;
        }
      }
      
$num_remaining_bytes -= $box->size;
    } while ( 
$num_remaining_bytes );
    return 
NOT_FOUND;
  }

  
/**
   * Parses an "iref" box.
   *
   * The "dimg" boxes contain links between tiles and their parent items, which
   * can be used to infer bit depth and number of channels for the primary item
   * when the latter does not have these properties.
   *
   * @param stream  $handle              The resource the box will be parsed from.
   * @param int     $num_remaining_bytes The number of bytes that should be available from the resource.
   * @return Status                      FOUND on success or an error on failure.
   */
  
private function parse_iref$num_remaining_bytes ) {
    do {
      
$box    = new Box();
      
$status $box->parse$this->handle$this->num_parsed_boxes$num_remaining_bytes );
      if ( 
$status != FOUND ) {
        return 
$status;
      }

      if ( 
$box->type == 'dimg' ) {
        
// See ISO/IEC 14496-12:2015(E) 8.11.12.2
        
$num_bytes_per_id = ( $box->version == ) ? 4;
        
$num_read_bytes   $num_bytes_per_id 2;
        if ( 
$box->content_size $num_read_bytes ) {
          return 
INVALID;
        }
        if ( !( 
$data read$this->handle$num_read_bytes ) ) ) {
          return 
TRUNCATED;
        }
        
$from_item_id    read_big_endian$data$num_bytes_per_id );
        
$reference_count read_big_endiansubstr$data$num_bytes_per_id), );

        for ( 
$i 0$i $reference_count; ++$i ) {
          if ( 
$i >= MAX_TILES ) {
            
$this->data_was_skipped true;
            break;
          }
          
$num_read_bytes += $num_bytes_per_id;
          if ( 
$box->content_size $num_read_bytes ) {
            return 
INVALID;
          }
          if ( !( 
$data read$this->handle$num_bytes_per_id ) ) ) {
            return 
TRUNCATED;
          }
          
$to_item_id read_big_endian$data$num_bytes_per_id );
          
$tile_count count$this->features->tiles );
          if ( 
$from_item_id <= MAX_VALUE && $to_item_id <= MAX_VALUE &&
               
$tile_count MAX_TILES ) {
            
$this->features->tiles[$tile_count]                 = new Tile();
            
$this->features->tiles[$tile_count]->tile_item_id   $to_item_id;
            
$this->features->tiles[$tile_count]->parent_item_id $from_item_id;
          } else {
            
$this->data_was_skipped true;
          }
        }

        
// If all features are available now, do not look further.
        
$status $this->features->get_primary_item_features();
        if ( 
$status != NOT_FOUND ) {
          return 
$status;
        }

        
// Mostly if 'data_was_skipped'.
        
if ( !skip$this->handle$box->content_size $num_read_bytes ) ) {
          return 
TRUNCATED;
        }
      } else {
        if ( !
skip$this->handle$box->content_size ) ) {
          return 
TRUNCATED;
        }
      }
      
$num_remaining_bytes -= $box->size;
    } while ( 
$num_remaining_bytes );
    return 
NOT_FOUND;
  }

  
/**
   * Parses a "meta" box.
   *
   * It looks for the primary item ID in the "pitm" box and recurses into other boxes
   * to find its features.
   *
   * @param stream  $handle              The resource the box will be parsed from.
   * @param int     $num_remaining_bytes The number of bytes that should be available from the resource.
   * @return Status                      FOUND on success or an error on failure.
   */
  
private function parse_meta$num_remaining_bytes ) {
    do {
      
$box    = new Box();
      
$status $box->parse$this->handle$this->num_parsed_boxes$num_remaining_bytes );
      if ( 
$status != FOUND ) {
        return 
$status;
      }

      if ( 
$box->type == 'pitm' ) {
        
// See ISO/IEC 14496-12:2015(E) 8.11.4.2
        
$num_bytes_per_id = ( $box->version == ) ? 4;
        if ( 
$num_bytes_per_id $num_remaining_bytes ) {
          return 
INVALID;
        }
        if ( !( 
$data read$this->handle$num_bytes_per_id ) ) ) {
          return 
TRUNCATED;
        }
        
$primary_item_id read_big_endian$data$num_bytes_per_id );
        if ( 
$primary_item_id MAX_VALUE ) {
          return 
ABORTED;
        }
        
$this->features->has_primary_item true;
        
$this->features->primary_item_id  $primary_item_id;
        if ( !
skip$this->handle$box->content_size $num_bytes_per_id ) ) {
          return 
TRUNCATED;
        }
      } else if ( 
$box->type == 'iprp' ) {
        
$status $this->parse_iprp$box->content_size );
        if ( 
$status != NOT_FOUND ) {
          return 
$status;
        }
      } else if ( 
$box->type == 'iref' ) {
        
$status $this->parse_iref$box->content_size );
        if ( 
$status != NOT_FOUND ) {
          return 
$status;
        }
      } else {
        if ( !
skip$this->handle$box->content_size ) ) {
          return 
TRUNCATED;
        }
      }
      
$num_remaining_bytes -= $box->size;
    } while ( 
$num_remaining_bytes != );
    
// According to ISO/IEC 14496-12:2012(E) 8.11.1.1 there is at most one "meta".
    
return INVALID;
  }

  
/**
   * Parses a file stream.
   *
   * The file type is checked through the "ftyp" box.
   *
   * @return bool True if the input stream is an AVIF bitstream or false.
   */
  
public function parse_ftyp() {
    
$box    = new Box();
    
$status $box->parse$this->handle$this->num_parsed_boxes );
    if ( 
$status != FOUND ) {
      return 
false;
    }

    if ( 
$box->type != 'ftyp' ) {
      return 
false;
    }
    
// Iterate over brands. See ISO/IEC 14496-12:2012(E) 4.3.1
    
if ( $box->content_size ) {
      return 
false;
    }
    for ( 
$i 0$i <= $box->content_size$i += ) {
      if ( !( 
$data read$this->handle) ) ) {
        return 
false;
      }
      if ( 
$i == ) {
        continue; 
// Skip minor_version.
      
}
      if ( 
substr$data0) == 'avif' || substr$data0) == 'avis' ) {
        return 
skip$this->handle$box->content_size - ( $i ) );
      }
      if ( 
$i 32 ) {
        return 
false// Be reasonable.
      
}

    }
    return 
false// No AVIF brand no good.
  
}

  
/**
   * Parses a file stream.
   *
   * Features are extracted from the "meta" box.
   *
   * @return bool True if the main features of the primary item were parsed or false.
   */
  
public function parse_file() {
    
$box = new Box();
    while ( 
$box->parse$this->handle$this->num_parsed_boxes ) == FOUND ) {
      if ( 
$box->type === 'meta' ) {
        if ( 
$this->parse_meta$box->content_size ) != FOUND ) {
          return 
false;
        }
        return 
true;
      }
      if ( !
skip$this->handle$box->content_size ) ) {
        return 
false;
      }
    }
    return 
false// No "meta" no good.
  
}
}

All system for education purposes only. For more tools: Telegram @jackleet

Mr.X Private Shell

Logo
-
New File | New Folder
Command
SQL