ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
GetId3\Write\Id3v2 Class Reference

GetId3() by James Heinrich info@.nosp@m.geti.nosp@m.d3.or.nosp@m.g //. More...

+ Collaboration diagram for GetId3\Write\Id3v2:

Public Member Functions

 __construct ()
 
 WriteID3v2 ()
 
 RemoveID3v2 ()
 
 GenerateID3v2TagFlags ($flags)
 
 GenerateID3v2FrameFlags ($TagAlter=false, $FileAlter=false, $ReadOnly=false, $Compression=false, $Encryption=false, $GroupingIdentity=false, $Unsynchronisation=false, $DataLengthIndicator=false)
 
 GenerateID3v2FrameData ($frame_name, $source_data_array)
 
 ID3v2FrameIsAllowed ($frame_name, $source_data_array)
 
 GenerateID3v2Tag ($noerrorsonly=true)
 
 ID3v2IsValidPriceString ($pricestring)
 
 ID3v2FrameFlagsLookupTagAlter ($framename)
 
 ID3v2FrameFlagsLookupFileAlter ($framename)
 
 ID3v2IsValidETCOevent ($eventid)
 
 ID3v2IsValidSYLTtype ($contenttype)
 
 ID3v2IsValidRVA2channeltype ($channeltype)
 
 ID3v2IsValidAPICpicturetype ($picturetype)
 
 ID3v2IsValidAPICimageformat ($imageformat)
 
 ID3v2IsValidCOMRreceivedAs ($receivedas)
 
 ID3v2IsValidRGADname ($RGADname)
 
 ID3v2IsValidRGADoriginator ($RGADoriginator)
 
 ID3v2IsValidTextEncoding ($textencodingbyte)
 array $ID3v2IsValidTextEncoding_cache More...
 
 Unsynchronise ($data)
 
 is_hash ($var)
 
 array_join_merge ($arr1, $arr2)
 
 IsValidMIMEstring ($mimestring)
 
 IsWithinBitRange ($number, $maxbits, $signed=false)
 
 safe_parse_url ($url)
 
 IsValidURL ($url, $allowUserPass=false)
 

Static Public Member Functions

static ID3v2ShortFrameNameLookup ($majorversion, $long_description)
 array $ID3v2ShortFrameNameLookup More...
 

Data Fields

 $filename
 
 $tag_data
 
 $fread_buffer_size = 32768
 
 $paddedlength = 4096
 
 $majorversion = 3
 
 $minorversion = 0
 
 $merge_existing_data = false
 
 $id3v2_default_encodingid = 0
 
 $id3v2_use_unsynchronisation = false
 
 $warnings = array()
 
 $errors = array()
 

Detailed Description

GetId3() by James Heinrich info@.nosp@m.geti.nosp@m.d3.or.nosp@m.g //.

// module for writing ID3v2 tags

Author
James Heinrich info@.nosp@m.geti.nosp@m.d3.or.nosp@m.g http://www.getid3.org Tag

Definition at line 31 of file Id3v2.php.

Constructor & Destructor Documentation

◆ __construct()

GetId3\Write\Id3v2::__construct ( )
Returns
boolean

Definition at line 85 of file Id3v2.php.

86  {
87  return true;
88  }

Member Function Documentation

◆ array_join_merge()

GetId3\Write\Id3v2::array_join_merge (   $arr1,
  $arr2 
)
Parameters
type$arr1
type$arr2
Returns
type

Definition at line 2019 of file Id3v2.php.

References array, GetId3\Write\Id3v2\array_join_merge(), and GetId3\Write\Id3v2\is_hash().

Referenced by GetId3\Write\Id3v2\array_join_merge(), and GetId3\Write\Id3v2\WriteID3v2().

2020  {
2021  // written by dev-nullØchristophe*vg
2022  // taken from http://www.php.net/manual/en/function.array-merge-recursive.php
2023  if (is_array($arr1) && is_array($arr2)) {
2024  // the same -> merge
2025  $new_array = array();
2026 
2027  if ($this->is_hash($arr1) && $this->is_hash($arr2)) {
2028  // hashes -> merge based on keys
2029  $keys = array_merge(array_keys($arr1), array_keys($arr2));
2030  foreach ($keys as $key) {
2031  $new_array[$key] = $this->array_join_merge((isset($arr1[$key]) ? $arr1[$key] : ''), (isset($arr2[$key]) ? $arr2[$key] : ''));
2032  }
2033  } else {
2034  // two real arrays -> merge
2035  $new_array = array_reverse(array_unique(array_reverse(array_merge($arr1, $arr2))));
2036  }
2037 
2038  return $new_array;
2039  } else {
2040  // not the same ... take new one if defined, else the old one stays
2041  return $arr2 ? $arr2 : $arr1;
2042  }
2043  }
Create styles array
The data for the language used.
array_join_merge($arr1, $arr2)
Definition: Id3v2.php:2019
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GenerateID3v2FrameData()

GetId3\Write\Id3v2::GenerateID3v2FrameData (   $frame_name,
  $source_data_array 
)
Parameters
type$frame_name
type$source_data_array
Returns
boolean

Definition at line 395 of file Id3v2.php.

References GetId3\Lib\Helper\BigEndian2String(), GetId3\Lib\Helper\Dec2Bin(), GetId3\Lib\Helper\Float2String(), GetId3\Write\Id3v2\ID3v2IsValidAPICimageformat(), GetId3\Write\Id3v2\ID3v2IsValidAPICpicturetype(), GetId3\Write\Id3v2\ID3v2IsValidCOMRreceivedAs(), GetId3\Write\Id3v2\ID3v2IsValidETCOevent(), GetId3\Write\Id3v2\ID3v2IsValidPriceString(), GetId3\Write\Id3v2\ID3v2IsValidRGADname(), GetId3\Write\Id3v2\ID3v2IsValidRGADoriginator(), GetId3\Write\Id3v2\ID3v2IsValidSYLTtype(), GetId3\Write\Id3v2\ID3v2IsValidTextEncoding(), GetId3\Module\Tag\Id3v2\IsANumber(), GetId3\Module\Tag\Id3v2\IsValidDateStampString(), GetId3\Module\Tag\Id3v2\IsValidID3v2FrameName(), GetId3\Write\Id3v2\IsValidMIMEstring(), GetId3\Write\Id3v2\IsValidURL(), GetId3\Write\Id3v2\IsWithinBitRange(), GetId3\Module\Tag\Id3v2\LanguageLookup(), GetId3\Lib\Helper\RGADgainString(), and GetId3\Module\Tag\Id3v2\TextEncodingTerminatorLookup().

Referenced by GetId3\Write\Id3v2\GenerateID3v2Tag().

396  {
397  if (!Tag\Id3v2::IsValidID3v2FrameName($frame_name, $this->majorversion)) {
398  return false;
399  }
400  $framedata = '';
401 
402  if (($this->majorversion < 3) || ($this->majorversion > 4)) {
403 
404  $this->errors[] = 'Only ID3v2.3 and ID3v2.4 are supported in GenerateID3v2FrameData()';
405 
406  } else { // $this->majorversion 3 or 4
407 
408  switch ($frame_name) {
409  case 'UFID':
410  // 4.1 UFID Unique file identifier
411  // Owner identifier <text string> $00
412  // Identifier <up to 64 bytes binary data>
413  if (strlen($source_data_array['data']) > 64) {
414  $this->errors[] = 'Identifier not allowed to be longer than 64 bytes in '.$frame_name.' (supplied data was '.strlen($source_data_array['data']).' bytes long)';
415  } else {
416  $framedata .= str_replace("\x00", '', $source_data_array['ownerid'])."\x00";
417  $framedata .= substr($source_data_array['data'], 0, 64); // max 64 bytes - truncate anything longer
418  }
419  break;
420 
421  case 'TXXX':
422  // 4.2.2 TXXX User defined text information frame
423  // Text encoding $xx
424  // Description <text string according to encoding> $00 (00)
425  // Value <text string according to encoding>
426  $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid);
427  if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'], $this->majorversion)) {
428  $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion;
429  } else {
430  $framedata .= chr($source_data_array['encodingid']);
431  $framedata .= $source_data_array['description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array['encodingid']);
432  $framedata .= $source_data_array['data'];
433  }
434  break;
435 
436  case 'WXXX':
437  // 4.3.2 WXXX User defined URL link frame
438  // Text encoding $xx
439  // Description <text string according to encoding> $00 (00)
440  // URL <text string>
441  $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid);
442  if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'], $this->majorversion)) {
443  $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion;
444  } elseif (!isset($source_data_array['data']) || !$this->IsValidURL($source_data_array['data'], false, false)) {
445  //$this->errors[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')';
446  // probably should be an error, need to rewrite IsValidURL() to handle other encodings
447  $this->warnings[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')';
448  } else {
449  $framedata .= chr($source_data_array['encodingid']);
450  $framedata .= $source_data_array['description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array['encodingid']);
451  $framedata .= $source_data_array['data'];
452  }
453  break;
454 
455  case 'IPLS':
456  // 4.4 IPLS Involved people list (ID3v2.3 only)
457  // Text encoding $xx
458  // People list strings <textstrings>
459  $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid);
460  if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'], $this->majorversion)) {
461  $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion;
462  } else {
463  $framedata .= chr($source_data_array['encodingid']);
464  $framedata .= $source_data_array['data'];
465  }
466  break;
467 
468  case 'MCDI':
469  // 4.4 MCDI Music CD identifier
470  // CD TOC <binary data>
471  $framedata .= $source_data_array['data'];
472  break;
473 
474  case 'ETCO':
475  // 4.5 ETCO Event timing codes
476  // Time stamp format $xx
477  // Where time stamp format is:
478  // $01 (32-bit value) MPEG frames from beginning of file
479  // $02 (32-bit value) milliseconds from beginning of file
480  // Followed by a list of key events in the following format:
481  // Type of event $xx
482  // Time stamp $xx (xx ...)
483  // The 'Time stamp' is set to zero if directly at the beginning of the sound
484  // or after the previous event. All events MUST be sorted in chronological order.
485  if (($source_data_array['timestampformat'] > 2) || ($source_data_array['timestampformat'] < 1)) {
486  $this->errors[] = 'Invalid Time Stamp Format byte in '.$frame_name.' ('.$source_data_array['timestampformat'].')';
487  } else {
488  $framedata .= chr($source_data_array['timestampformat']);
489  foreach ($source_data_array as $key => $val) {
490  if (!$this->ID3v2IsValidETCOevent($val['typeid'])) {
491  $this->errors[] = 'Invalid Event Type byte in '.$frame_name.' ('.$val['typeid'].')';
492  } elseif (($key != 'timestampformat') && ($key != 'flags')) {
493  if (($val['timestamp'] > 0) && ($previousETCOtimestamp >= $val['timestamp'])) {
494  // The 'Time stamp' is set to zero if directly at the beginning of the sound
495  // or after the previous event. All events MUST be sorted in chronological order.
496  $this->errors[] = 'Out-of-order timestamp in '.$frame_name.' ('.$val['timestamp'].') for Event Type ('.$val['typeid'].')';
497  } else {
498  $framedata .= chr($val['typeid']);
499  $framedata .= Helper::BigEndian2String($val['timestamp'], 4, false);
500  }
501  }
502  }
503  }
504  break;
505 
506  case 'MLLT':
507  // 4.6 MLLT MPEG location lookup table
508  // MPEG frames between reference $xx xx
509  // Bytes between reference $xx xx xx
510  // Milliseconds between reference $xx xx xx
511  // Bits for bytes deviation $xx
512  // Bits for milliseconds dev. $xx
513  // Then for every reference the following data is included;
514  // Deviation in bytes %xxx....
515  // Deviation in milliseconds %xxx....
516  if (($source_data_array['framesbetweenreferences'] > 0) && ($source_data_array['framesbetweenreferences'] <= 65535)) {
517  $framedata .= Helper::BigEndian2String($source_data_array['framesbetweenreferences'], 2, false);
518  } else {
519  $this->errors[] = 'Invalid MPEG Frames Between References in '.$frame_name.' ('.$source_data_array['framesbetweenreferences'].')';
520  }
521  if (($source_data_array['bytesbetweenreferences'] > 0) && ($source_data_array['bytesbetweenreferences'] <= 16777215)) {
522  $framedata .= Helper::BigEndian2String($source_data_array['bytesbetweenreferences'], 3, false);
523  } else {
524  $this->errors[] = 'Invalid bytes Between References in '.$frame_name.' ('.$source_data_array['bytesbetweenreferences'].')';
525  }
526  if (($source_data_array['msbetweenreferences'] > 0) && ($source_data_array['msbetweenreferences'] <= 16777215)) {
527  $framedata .= Helper::BigEndian2String($source_data_array['msbetweenreferences'], 3, false);
528  } else {
529  $this->errors[] = 'Invalid Milliseconds Between References in '.$frame_name.' ('.$source_data_array['msbetweenreferences'].')';
530  }
531  if (!$this->IsWithinBitRange($source_data_array['bitsforbytesdeviation'], 8, false)) {
532  if (($source_data_array['bitsforbytesdeviation'] % 4) == 0) {
533  $framedata .= chr($source_data_array['bitsforbytesdeviation']);
534  } else {
535  $this->errors[] = 'Bits For Bytes Deviation in '.$frame_name.' ('.$source_data_array['bitsforbytesdeviation'].') must be a multiple of 4.';
536  }
537  } else {
538  $this->errors[] = 'Invalid Bits For Bytes Deviation in '.$frame_name.' ('.$source_data_array['bitsforbytesdeviation'].')';
539  }
540  if (!$this->IsWithinBitRange($source_data_array['bitsformsdeviation'], 8, false)) {
541  if (($source_data_array['bitsformsdeviation'] % 4) == 0) {
542  $framedata .= chr($source_data_array['bitsformsdeviation']);
543  } else {
544  $this->errors[] = 'Bits For Milliseconds Deviation in '.$frame_name.' ('.$source_data_array['bitsforbytesdeviation'].') must be a multiple of 4.';
545  }
546  } else {
547  $this->errors[] = 'Invalid Bits For Milliseconds Deviation in '.$frame_name.' ('.$source_data_array['bitsformsdeviation'].')';
548  }
549  foreach ($source_data_array as $key => $val) {
550  if (($key != 'framesbetweenreferences') && ($key != 'bytesbetweenreferences') && ($key != 'msbetweenreferences') && ($key != 'bitsforbytesdeviation') && ($key != 'bitsformsdeviation') && ($key != 'flags')) {
551  $unwrittenbitstream .= str_pad(Helper::Dec2Bin($val['bytedeviation']), $source_data_array['bitsforbytesdeviation'], '0', STR_PAD_LEFT);
552  $unwrittenbitstream .= str_pad(Helper::Dec2Bin($val['msdeviation']), $source_data_array['bitsformsdeviation'], '0', STR_PAD_LEFT);
553  }
554  }
555  for ($i = 0; $i < strlen($unwrittenbitstream); $i += 8) {
556  $highnibble = bindec(substr($unwrittenbitstream, $i, 4)) << 4;
557  $lownibble = bindec(substr($unwrittenbitstream, $i + 4, 4));
558  $framedata .= chr($highnibble & $lownibble);
559  }
560  break;
561 
562  case 'SYTC':
563  // 4.7 SYTC Synchronised tempo codes
564  // Time stamp format $xx
565  // Tempo data <binary data>
566  // Where time stamp format is:
567  // $01 (32-bit value) MPEG frames from beginning of file
568  // $02 (32-bit value) milliseconds from beginning of file
569  if (($source_data_array['timestampformat'] > 2) || ($source_data_array['timestampformat'] < 1)) {
570  $this->errors[] = 'Invalid Time Stamp Format byte in '.$frame_name.' ('.$source_data_array['timestampformat'].')';
571  } else {
572  $framedata .= chr($source_data_array['timestampformat']);
573  foreach ($source_data_array as $key => $val) {
574  if (!$this->ID3v2IsValidETCOevent($val['typeid'])) {
575  $this->errors[] = 'Invalid Event Type byte in '.$frame_name.' ('.$val['typeid'].')';
576  } elseif (($key != 'timestampformat') && ($key != 'flags')) {
577  if (($val['tempo'] < 0) || ($val['tempo'] > 510)) {
578  $this->errors[] = 'Invalid Tempo (max = 510) in '.$frame_name.' ('.$val['tempo'].') at timestamp ('.$val['timestamp'].')';
579  } else {
580  if ($val['tempo'] > 255) {
581  $framedata .= chr(255);
582  $val['tempo'] -= 255;
583  }
584  $framedata .= chr($val['tempo']);
585  $framedata .= Helper::BigEndian2String($val['timestamp'], 4, false);
586  }
587  }
588  }
589  }
590  break;
591 
592  case 'USLT':
593  // 4.8 USLT Unsynchronised lyric/text transcription
594  // Text encoding $xx
595  // Language $xx xx xx
596  // Content descriptor <text string according to encoding> $00 (00)
597  // Lyrics/text <full text string according to encoding>
598  $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid);
599  if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) {
600  $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion;
601  } elseif (Tag\Id3v2::LanguageLookup($source_data_array['language'], true) == '') {
602  $this->errors[] = 'Invalid Language in '.$frame_name.' ('.$source_data_array['language'].')';
603  } else {
604  $framedata .= chr($source_data_array['encodingid']);
605  $framedata .= strtolower($source_data_array['language']);
606  $framedata .= $source_data_array['description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array['encodingid']);
607  $framedata .= $source_data_array['data'];
608  }
609  break;
610 
611  case 'SYLT':
612  // 4.9 SYLT Synchronised lyric/text
613  // Text encoding $xx
614  // Language $xx xx xx
615  // Time stamp format $xx
616  // $01 (32-bit value) MPEG frames from beginning of file
617  // $02 (32-bit value) milliseconds from beginning of file
618  // Content type $xx
619  // Content descriptor <text string according to encoding> $00 (00)
620  // Terminated text to be synced (typically a syllable)
621  // Sync identifier (terminator to above string) $00 (00)
622  // Time stamp $xx (xx ...)
623  $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid);
624  if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) {
625  $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion;
626  } elseif (Tag\Id3v2::LanguageLookup($source_data_array['language'], true) == '') {
627  $this->errors[] = 'Invalid Language in '.$frame_name.' ('.$source_data_array['language'].')';
628  } elseif (($source_data_array['timestampformat'] > 2) || ($source_data_array['timestampformat'] < 1)) {
629  $this->errors[] = 'Invalid Time Stamp Format byte in '.$frame_name.' ('.$source_data_array['timestampformat'].')';
630  } elseif (!$this->ID3v2IsValidSYLTtype($source_data_array['contenttypeid'])) {
631  $this->errors[] = 'Invalid Content Type byte in '.$frame_name.' ('.$source_data_array['contenttypeid'].')';
632  } elseif (!is_array($source_data_array['data'])) {
633  $this->errors[] = 'Invalid Lyric/Timestamp data in '.$frame_name.' (must be an array)';
634  } else {
635  $framedata .= chr($source_data_array['encodingid']);
636  $framedata .= strtolower($source_data_array['language']);
637  $framedata .= chr($source_data_array['timestampformat']);
638  $framedata .= chr($source_data_array['contenttypeid']);
639  $framedata .= $source_data_array['description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array['encodingid']);
640  ksort($source_data_array['data']);
641  foreach ($source_data_array['data'] as $key => $val) {
642  $framedata .= $val['data'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array['encodingid']);
643  $framedata .= Helper::BigEndian2String($val['timestamp'], 4, false);
644  }
645  }
646  break;
647 
648  case 'COMM':
649  // 4.10 COMM Comments
650  // Text encoding $xx
651  // Language $xx xx xx
652  // Short content descrip. <text string according to encoding> $00 (00)
653  // The actual text <full text string according to encoding>
654  $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid);
655  if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) {
656  $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion;
657  } elseif (Tag\Id3v2::LanguageLookup($source_data_array['language'], true) == '') {
658  $this->errors[] = 'Invalid Language in '.$frame_name.' ('.$source_data_array['language'].')';
659  } else {
660  $framedata .= chr($source_data_array['encodingid']);
661  $framedata .= strtolower($source_data_array['language']);
662  $framedata .= $source_data_array['description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array['encodingid']);
663  $framedata .= $source_data_array['data'];
664  }
665  break;
666 
667  case 'RVA2':
668  // 4.11 RVA2 Relative volume adjustment (2) (ID3v2.4+ only)
669  // Identification <text string> $00
670  // The 'identification' string is used to identify the situation and/or
671  // device where this adjustment should apply. The following is then
672  // repeated for every channel:
673  // Type of channel $xx
674  // Volume adjustment $xx xx
675  // Bits representing peak $xx
676  // Peak volume $xx (xx ...)
677  $framedata .= str_replace("\x00", '', $source_data_array['description'])."\x00";
678  foreach ($source_data_array as $key => $val) {
679  if ($key != 'description') {
680  $framedata .= chr($val['channeltypeid']);
681  $framedata .= Helper::BigEndian2String($val['volumeadjust'], 2, false, true); // signed 16-bit
682  if (!$this->IsWithinBitRange($source_data_array['bitspeakvolume'], 8, false)) {
683  $framedata .= chr($val['bitspeakvolume']);
684  if ($val['bitspeakvolume'] > 0) {
685  $framedata .= Helper::BigEndian2String($val['peakvolume'], ceil($val['bitspeakvolume'] / 8), false, false);
686  }
687  } else {
688  $this->errors[] = 'Invalid Bits Representing Peak Volume in '.$frame_name.' ('.$val['bitspeakvolume'].') (range = 0 to 255)';
689  }
690  }
691  }
692  break;
693 
694  case 'RVAD':
695  // 4.12 RVAD Relative volume adjustment (ID3v2.3 only)
696  // Increment/decrement %00fedcba
697  // Bits used for volume descr. $xx
698  // Relative volume change, right $xx xx (xx ...) // a
699  // Relative volume change, left $xx xx (xx ...) // b
700  // Peak volume right $xx xx (xx ...)
701  // Peak volume left $xx xx (xx ...)
702  // Relative volume change, right back $xx xx (xx ...) // c
703  // Relative volume change, left back $xx xx (xx ...) // d
704  // Peak volume right back $xx xx (xx ...)
705  // Peak volume left back $xx xx (xx ...)
706  // Relative volume change, center $xx xx (xx ...) // e
707  // Peak volume center $xx xx (xx ...)
708  // Relative volume change, bass $xx xx (xx ...) // f
709  // Peak volume bass $xx xx (xx ...)
710  if (!$this->IsWithinBitRange($source_data_array['bitsvolume'], 8, false)) {
711  $this->errors[] = 'Invalid Bits For Volume Description byte in '.$frame_name.' ('.$source_data_array['bitsvolume'].') (range = 1 to 255)';
712  } else {
713  $incdecflag .= '00';
714  $incdecflag .= $source_data_array['incdec']['right'] ? '1' : '0'; // a - Relative volume change, right
715  $incdecflag .= $source_data_array['incdec']['left'] ? '1' : '0'; // b - Relative volume change, left
716  $incdecflag .= $source_data_array['incdec']['rightrear'] ? '1' : '0'; // c - Relative volume change, right back
717  $incdecflag .= $source_data_array['incdec']['leftrear'] ? '1' : '0'; // d - Relative volume change, left back
718  $incdecflag .= $source_data_array['incdec']['center'] ? '1' : '0'; // e - Relative volume change, center
719  $incdecflag .= $source_data_array['incdec']['bass'] ? '1' : '0'; // f - Relative volume change, bass
720  $framedata .= chr(bindec($incdecflag));
721  $framedata .= chr($source_data_array['bitsvolume']);
722  $framedata .= Helper::BigEndian2String($source_data_array['volumechange']['right'], ceil($source_data_array['bitsvolume'] / 8), false);
723  $framedata .= Helper::BigEndian2String($source_data_array['volumechange']['left'], ceil($source_data_array['bitsvolume'] / 8), false);
724  $framedata .= Helper::BigEndian2String($source_data_array['peakvolume']['right'], ceil($source_data_array['bitsvolume'] / 8), false);
725  $framedata .= Helper::BigEndian2String($source_data_array['peakvolume']['left'], ceil($source_data_array['bitsvolume'] / 8), false);
726  if ($source_data_array['volumechange']['rightrear'] || $source_data_array['volumechange']['leftrear'] ||
727  $source_data_array['peakvolume']['rightrear'] || $source_data_array['peakvolume']['leftrear'] ||
728  $source_data_array['volumechange']['center'] || $source_data_array['peakvolume']['center'] ||
729  $source_data_array['volumechange']['bass'] || $source_data_array['peakvolume']['bass']) {
730  $framedata .= Helper::BigEndian2String($source_data_array['volumechange']['rightrear'], ceil($source_data_array['bitsvolume']/8), false);
731  $framedata .= Helper::BigEndian2String($source_data_array['volumechange']['leftrear'], ceil($source_data_array['bitsvolume']/8), false);
732  $framedata .= Helper::BigEndian2String($source_data_array['peakvolume']['rightrear'], ceil($source_data_array['bitsvolume']/8), false);
733  $framedata .= Helper::BigEndian2String($source_data_array['peakvolume']['leftrear'], ceil($source_data_array['bitsvolume']/8), false);
734  }
735  if ($source_data_array['volumechange']['center'] || $source_data_array['peakvolume']['center'] ||
736  $source_data_array['volumechange']['bass'] || $source_data_array['peakvolume']['bass']) {
737  $framedata .= Helper::BigEndian2String($source_data_array['volumechange']['center'], ceil($source_data_array['bitsvolume']/8), false);
738  $framedata .= Helper::BigEndian2String($source_data_array['peakvolume']['center'], ceil($source_data_array['bitsvolume']/8), false);
739  }
740  if ($source_data_array['volumechange']['bass'] || $source_data_array['peakvolume']['bass']) {
741  $framedata .= Helper::BigEndian2String($source_data_array['volumechange']['bass'], ceil($source_data_array['bitsvolume']/8), false);
742  $framedata .= Helper::BigEndian2String($source_data_array['peakvolume']['bass'], ceil($source_data_array['bitsvolume']/8), false);
743  }
744  }
745  break;
746 
747  case 'EQU2':
748  // 4.12 EQU2 Equalisation (2) (ID3v2.4+ only)
749  // Interpolation method $xx
750  // $00 Band
751  // $01 Linear
752  // Identification <text string> $00
753  // The following is then repeated for every adjustment point
754  // Frequency $xx xx
755  // Volume adjustment $xx xx
756  if (($source_data_array['interpolationmethod'] < 0) || ($source_data_array['interpolationmethod'] > 1)) {
757  $this->errors[] = 'Invalid Interpolation Method byte in '.$frame_name.' ('.$source_data_array['interpolationmethod'].') (valid = 0 or 1)';
758  } else {
759  $framedata .= chr($source_data_array['interpolationmethod']);
760  $framedata .= str_replace("\x00", '', $source_data_array['description'])."\x00";
761  foreach ($source_data_array['data'] as $key => $val) {
762  $framedata .= Helper::BigEndian2String(intval(round($key * 2)), 2, false);
763  $framedata .= Helper::BigEndian2String($val, 2, false, true); // signed 16-bit
764  }
765  }
766  break;
767 
768  case 'EQUA':
769  // 4.12 EQUA Equalisation (ID3v2.3 only)
770  // Adjustment bits $xx
771  // This is followed by 2 bytes + ('adjustment bits' rounded up to the
772  // nearest byte) for every equalisation band in the following format,
773  // giving a frequency range of 0 - 32767Hz:
774  // Increment/decrement %x (MSB of the Frequency)
775  // Frequency (lower 15 bits)
776  // Adjustment $xx (xx ...)
777  if (!$this->IsWithinBitRange($source_data_array['bitsvolume'], 8, false)) {
778  $this->errors[] = 'Invalid Adjustment Bits byte in '.$frame_name.' ('.$source_data_array['bitsvolume'].') (range = 1 to 255)';
779  } else {
780  $framedata .= chr($source_data_array['adjustmentbits']);
781  foreach ($source_data_array as $key => $val) {
782  if ($key != 'bitsvolume') {
783  if (($key > 32767) || ($key < 0)) {
784  $this->errors[] = 'Invalid Frequency in '.$frame_name.' ('.$key.') (range = 0 to 32767)';
785  } else {
786  if ($val >= 0) {
787  // put MSB of frequency to 1 if increment, 0 if decrement
788  $key |= 0x8000;
789  }
790  $framedata .= Helper::BigEndian2String($key, 2, false);
791  $framedata .= Helper::BigEndian2String($val, ceil($source_data_array['adjustmentbits'] / 8), false);
792  }
793  }
794  }
795  }
796  break;
797 
798  case 'RVRB':
799  // 4.13 RVRB Reverb
800  // Reverb left (ms) $xx xx
801  // Reverb right (ms) $xx xx
802  // Reverb bounces, left $xx
803  // Reverb bounces, right $xx
804  // Reverb feedback, left to left $xx
805  // Reverb feedback, left to right $xx
806  // Reverb feedback, right to right $xx
807  // Reverb feedback, right to left $xx
808  // Premix left to right $xx
809  // Premix right to left $xx
810  if (!$this->IsWithinBitRange($source_data_array['left'], 16, false)) {
811  $this->errors[] = 'Invalid Reverb Left in '.$frame_name.' ('.$source_data_array['left'].') (range = 0 to 65535)';
812  } elseif (!$this->IsWithinBitRange($source_data_array['right'], 16, false)) {
813  $this->errors[] = 'Invalid Reverb Left in '.$frame_name.' ('.$source_data_array['right'].') (range = 0 to 65535)';
814  } elseif (!$this->IsWithinBitRange($source_data_array['bouncesL'], 8, false)) {
815  $this->errors[] = 'Invalid Reverb Bounces, Left in '.$frame_name.' ('.$source_data_array['bouncesL'].') (range = 0 to 255)';
816  } elseif (!$this->IsWithinBitRange($source_data_array['bouncesR'], 8, false)) {
817  $this->errors[] = 'Invalid Reverb Bounces, Right in '.$frame_name.' ('.$source_data_array['bouncesR'].') (range = 0 to 255)';
818  } elseif (!$this->IsWithinBitRange($source_data_array['feedbackLL'], 8, false)) {
819  $this->errors[] = 'Invalid Reverb Feedback, Left-To-Left in '.$frame_name.' ('.$source_data_array['feedbackLL'].') (range = 0 to 255)';
820  } elseif (!$this->IsWithinBitRange($source_data_array['feedbackLR'], 8, false)) {
821  $this->errors[] = 'Invalid Reverb Feedback, Left-To-Right in '.$frame_name.' ('.$source_data_array['feedbackLR'].') (range = 0 to 255)';
822  } elseif (!$this->IsWithinBitRange($source_data_array['feedbackRR'], 8, false)) {
823  $this->errors[] = 'Invalid Reverb Feedback, Right-To-Right in '.$frame_name.' ('.$source_data_array['feedbackRR'].') (range = 0 to 255)';
824  } elseif (!$this->IsWithinBitRange($source_data_array['feedbackRL'], 8, false)) {
825  $this->errors[] = 'Invalid Reverb Feedback, Right-To-Left in '.$frame_name.' ('.$source_data_array['feedbackRL'].') (range = 0 to 255)';
826  } elseif (!$this->IsWithinBitRange($source_data_array['premixLR'], 8, false)) {
827  $this->errors[] = 'Invalid Premix, Left-To-Right in '.$frame_name.' ('.$source_data_array['premixLR'].') (range = 0 to 255)';
828  } elseif (!$this->IsWithinBitRange($source_data_array['premixRL'], 8, false)) {
829  $this->errors[] = 'Invalid Premix, Right-To-Left in '.$frame_name.' ('.$source_data_array['premixRL'].') (range = 0 to 255)';
830  } else {
831  $framedata .= Helper::BigEndian2String($source_data_array['left'], 2, false);
832  $framedata .= Helper::BigEndian2String($source_data_array['right'], 2, false);
833  $framedata .= chr($source_data_array['bouncesL']);
834  $framedata .= chr($source_data_array['bouncesR']);
835  $framedata .= chr($source_data_array['feedbackLL']);
836  $framedata .= chr($source_data_array['feedbackLR']);
837  $framedata .= chr($source_data_array['feedbackRR']);
838  $framedata .= chr($source_data_array['feedbackRL']);
839  $framedata .= chr($source_data_array['premixLR']);
840  $framedata .= chr($source_data_array['premixRL']);
841  }
842  break;
843 
844  case 'APIC':
845  // 4.14 APIC Attached picture
846  // Text encoding $xx
847  // MIME type <text string> $00
848  // Picture type $xx
849  // Description <text string according to encoding> $00 (00)
850  // Picture data <binary data>
851  $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid);
852  if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) {
853  $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion;
854  } elseif (!$this->ID3v2IsValidAPICpicturetype($source_data_array['picturetypeid'])) {
855  $this->errors[] = 'Invalid Picture Type byte in '.$frame_name.' ('.$source_data_array['picturetypeid'].') for ID3v2.'.$this->majorversion;
856  } elseif (($this->majorversion >= 3) && (!$this->ID3v2IsValidAPICimageformat($source_data_array['mime']))) {
857  $this->errors[] = 'Invalid MIME Type in '.$frame_name.' ('.$source_data_array['mime'].') for ID3v2.'.$this->majorversion;
858  } elseif (($source_data_array['mime'] == '-->') && (!$this->IsValidURL($source_data_array['data'], false, false))) {
859  //$this->errors[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')';
860  // probably should be an error, need to rewrite IsValidURL() to handle other encodings
861  $this->warnings[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')';
862  } else {
863  $framedata .= chr($source_data_array['encodingid']);
864  $framedata .= str_replace("\x00", '', $source_data_array['mime'])."\x00";
865  $framedata .= chr($source_data_array['picturetypeid']);
866  $framedata .= (!empty($source_data_array['description']) ? $source_data_array['description'] : '').Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array['encodingid']);
867  $framedata .= $source_data_array['data'];
868  }
869  break;
870 
871  case 'GEOB':
872  // 4.15 GEOB General encapsulated object
873  // Text encoding $xx
874  // MIME type <text string> $00
875  // Filename <text string according to encoding> $00 (00)
876  // Content description <text string according to encoding> $00 (00)
877  // Encapsulated object <binary data>
878  $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid);
879  if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) {
880  $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion;
881  } elseif (!$this->IsValidMIMEstring($source_data_array['mime'])) {
882  $this->errors[] = 'Invalid MIME Type in '.$frame_name.' ('.$source_data_array['mime'].')';
883  } elseif (!$source_data_array['description']) {
884  $this->errors[] = 'Missing Description in '.$frame_name;
885  } else {
886  $framedata .= chr($source_data_array['encodingid']);
887  $framedata .= str_replace("\x00", '', $source_data_array['mime'])."\x00";
888  $framedata .= $source_data_array['filename'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array['encodingid']);
889  $framedata .= $source_data_array['description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array['encodingid']);
890  $framedata .= $source_data_array['data'];
891  }
892  break;
893 
894  case 'PCNT':
895  // 4.16 PCNT Play counter
896  // When the counter reaches all one's, one byte is inserted in
897  // front of the counter thus making the counter eight bits bigger
898  // Counter $xx xx xx xx (xx ...)
899  $framedata .= Helper::BigEndian2String($source_data_array['data'], 4, false);
900  break;
901 
902  case 'POPM':
903  // 4.17 POPM Popularimeter
904  // When the counter reaches all one's, one byte is inserted in
905  // front of the counter thus making the counter eight bits bigger
906  // Email to user <text string> $00
907  // Rating $xx
908  // Counter $xx xx xx xx (xx ...)
909  if (!$this->IsWithinBitRange($source_data_array['rating'], 8, false)) {
910  $this->errors[] = 'Invalid Rating byte in '.$frame_name.' ('.$source_data_array['rating'].') (range = 0 to 255)';
911  } elseif (!IsValidEmail($source_data_array['email'])) {
912  $this->errors[] = 'Invalid Email in '.$frame_name.' ('.$source_data_array['email'].')';
913  } else {
914  $framedata .= str_replace("\x00", '', $source_data_array['email'])."\x00";
915  $framedata .= chr($source_data_array['rating']);
916  $framedata .= Helper::BigEndian2String($source_data_array['data'], 4, false);
917  }
918  break;
919 
920  case 'RBUF':
921  // 4.18 RBUF Recommended buffer size
922  // Buffer size $xx xx xx
923  // Embedded info flag %0000000x
924  // Offset to next tag $xx xx xx xx
925  if (!$this->IsWithinBitRange($source_data_array['buffersize'], 24, false)) {
926  $this->errors[] = 'Invalid Buffer Size in '.$frame_name;
927  } elseif (!$this->IsWithinBitRange($source_data_array['nexttagoffset'], 32, false)) {
928  $this->errors[] = 'Invalid Offset To Next Tag in '.$frame_name;
929  } else {
930  $framedata .= Helper::BigEndian2String($source_data_array['buffersize'], 3, false);
931  $flag .= '0000000';
932  $flag .= $source_data_array['flags']['embededinfo'] ? '1' : '0';
933  $framedata .= chr(bindec($flag));
934  $framedata .= Helper::BigEndian2String($source_data_array['nexttagoffset'], 4, false);
935  }
936  break;
937 
938  case 'AENC':
939  // 4.19 AENC Audio encryption
940  // Owner identifier <text string> $00
941  // Preview start $xx xx
942  // Preview length $xx xx
943  // Encryption info <binary data>
944  if (!$this->IsWithinBitRange($source_data_array['previewstart'], 16, false)) {
945  $this->errors[] = 'Invalid Preview Start in '.$frame_name.' ('.$source_data_array['previewstart'].')';
946  } elseif (!$this->IsWithinBitRange($source_data_array['previewlength'], 16, false)) {
947  $this->errors[] = 'Invalid Preview Length in '.$frame_name.' ('.$source_data_array['previewlength'].')';
948  } else {
949  $framedata .= str_replace("\x00", '', $source_data_array['ownerid'])."\x00";
950  $framedata .= Helper::BigEndian2String($source_data_array['previewstart'], 2, false);
951  $framedata .= Helper::BigEndian2String($source_data_array['previewlength'], 2, false);
952  $framedata .= $source_data_array['encryptioninfo'];
953  }
954  break;
955 
956  case 'LINK':
957  // 4.20 LINK Linked information
958  // Frame identifier $xx xx xx xx
959  // URL <text string> $00
960  // ID and additional data <text string(s)>
961  if (!Tag\Id3v2::IsValidID3v2FrameName($source_data_array['frameid'], $this->majorversion)) {
962  $this->errors[] = 'Invalid Frame Identifier in '.$frame_name.' ('.$source_data_array['frameid'].')';
963  } elseif (!$this->IsValidURL($source_data_array['data'], true, false)) {
964  //$this->errors[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')';
965  // probably should be an error, need to rewrite IsValidURL() to handle other encodings
966  $this->warnings[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')';
967  } elseif ((($source_data_array['frameid'] == 'AENC') || ($source_data_array['frameid'] == 'APIC') || ($source_data_array['frameid'] == 'GEOB') || ($source_data_array['frameid'] == 'TXXX')) && ($source_data_array['additionaldata'] == '')) {
968  $this->errors[] = 'Content Descriptor must be specified as additional data for Frame Identifier of '.$source_data_array['frameid'].' in '.$frame_name;
969  } elseif (($source_data_array['frameid'] == 'USER') && (Tag\Id3v2::LanguageLookup($source_data_array['additionaldata'], true) == '')) {
970  $this->errors[] = 'Language must be specified as additional data for Frame Identifier of '.$source_data_array['frameid'].' in '.$frame_name;
971  } elseif (($source_data_array['frameid'] == 'PRIV') && ($source_data_array['additionaldata'] == '')) {
972  $this->errors[] = 'Owner Identifier must be specified as additional data for Frame Identifier of '.$source_data_array['frameid'].' in '.$frame_name;
973  } elseif ((($source_data_array['frameid'] == 'COMM') || ($source_data_array['frameid'] == 'SYLT') || ($source_data_array['frameid'] == 'USLT')) && ((Tag\Id3v2::LanguageLookup(substr($source_data_array['additionaldata'], 0, 3), true) == '') || (substr($source_data_array['additionaldata'], 3) == ''))) {
974  $this->errors[] = 'Language followed by Content Descriptor must be specified as additional data for Frame Identifier of '.$source_data_array['frameid'].' in '.$frame_name;
975  } else {
976  $framedata .= $source_data_array['frameid'];
977  $framedata .= str_replace("\x00", '', $source_data_array['data'])."\x00";
978  switch ($source_data_array['frameid']) {
979  case 'COMM':
980  case 'SYLT':
981  case 'USLT':
982  case 'PRIV':
983  case 'USER':
984  case 'AENC':
985  case 'APIC':
986  case 'GEOB':
987  case 'TXXX':
988  $framedata .= $source_data_array['additionaldata'];
989  break;
990  case 'ASPI':
991  case 'ETCO':
992  case 'EQU2':
993  case 'MCID':
994  case 'MLLT':
995  case 'OWNE':
996  case 'RVA2':
997  case 'RVRB':
998  case 'SYTC':
999  case 'IPLS':
1000  case 'RVAD':
1001  case 'EQUA':
1002  // no additional data required
1003  break;
1004  case 'RBUF':
1005  if ($this->majorversion == 3) {
1006  // no additional data required
1007  } else {
1008  $this->errors[] = $source_data_array['frameid'].' is not a valid Frame Identifier in '.$frame_name.' (in ID3v2.'.$this->majorversion.')';
1009  }
1010 
1011  default:
1012  if ((substr($source_data_array['frameid'], 0, 1) == 'T') || (substr($source_data_array['frameid'], 0, 1) == 'W')) {
1013  // no additional data required
1014  } else {
1015  $this->errors[] = $source_data_array['frameid'].' is not a valid Frame Identifier in '.$frame_name.' (in ID3v2.'.$this->majorversion.')';
1016  }
1017  break;
1018  }
1019  }
1020  break;
1021 
1022  case 'POSS':
1023  // 4.21 POSS Position synchronisation frame (ID3v2.3+ only)
1024  // Time stamp format $xx
1025  // Position $xx (xx ...)
1026  if (($source_data_array['timestampformat'] < 1) || ($source_data_array['timestampformat'] > 2)) {
1027  $this->errors[] = 'Invalid Time Stamp Format in '.$frame_name.' ('.$source_data_array['timestampformat'].') (valid = 1 or 2)';
1028  } elseif (!$this->IsWithinBitRange($source_data_array['position'], 32, false)) {
1029  $this->errors[] = 'Invalid Position in '.$frame_name.' ('.$source_data_array['position'].') (range = 0 to 4294967295)';
1030  } else {
1031  $framedata .= chr($source_data_array['timestampformat']);
1032  $framedata .= Helper::BigEndian2String($source_data_array['position'], 4, false);
1033  }
1034  break;
1035 
1036  case 'USER':
1037  // 4.22 USER Terms of use (ID3v2.3+ only)
1038  // Text encoding $xx
1039  // Language $xx xx xx
1040  // The actual text <text string according to encoding>
1041  $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid);
1042  if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) {
1043  $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].')';
1044  } elseif (Tag\Id3v2::LanguageLookup($source_data_array['language'], true) == '') {
1045  $this->errors[] = 'Invalid Language in '.$frame_name.' ('.$source_data_array['language'].')';
1046  } else {
1047  $framedata .= chr($source_data_array['encodingid']);
1048  $framedata .= strtolower($source_data_array['language']);
1049  $framedata .= $source_data_array['data'];
1050  }
1051  break;
1052 
1053  case 'OWNE':
1054  // 4.23 OWNE Ownership frame (ID3v2.3+ only)
1055  // Text encoding $xx
1056  // Price paid <text string> $00
1057  // Date of purch. <text string>
1058  // Seller <text string according to encoding>
1059  $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid);
1060  if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) {
1061  $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].')';
1062  } elseif (!$this->IsANumber($source_data_array['pricepaid']['value'], false)) {
1063  $this->errors[] = 'Invalid Price Paid in '.$frame_name.' ('.$source_data_array['pricepaid']['value'].')';
1064  } elseif (!$this->IsValidDateStampString($source_data_array['purchasedate'])) {
1065  $this->errors[] = 'Invalid Date Of Purchase in '.$frame_name.' ('.$source_data_array['purchasedate'].') (format = YYYYMMDD)';
1066  } else {
1067  $framedata .= chr($source_data_array['encodingid']);
1068  $framedata .= str_replace("\x00", '', $source_data_array['pricepaid']['value'])."\x00";
1069  $framedata .= $source_data_array['purchasedate'];
1070  $framedata .= $source_data_array['seller'];
1071  }
1072  break;
1073 
1074  case 'COMR':
1075  // 4.24 COMR Commercial frame (ID3v2.3+ only)
1076  // Text encoding $xx
1077  // Price string <text string> $00
1078  // Valid until <text string>
1079  // Contact URL <text string> $00
1080  // Received as $xx
1081  // Name of seller <text string according to encoding> $00 (00)
1082  // Description <text string according to encoding> $00 (00)
1083  // Picture MIME type <string> $00
1084  // Seller logo <binary data>
1085  $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid);
1086  if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) {
1087  $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].')';
1088  } elseif (!$this->IsValidDateStampString($source_data_array['pricevaliduntil'])) {
1089  $this->errors[] = 'Invalid Valid Until date in '.$frame_name.' ('.$source_data_array['pricevaliduntil'].') (format = YYYYMMDD)';
1090  } elseif (!$this->IsValidURL($source_data_array['contacturl'], false, true)) {
1091  $this->errors[] = 'Invalid Contact URL in '.$frame_name.' ('.$source_data_array['contacturl'].') (allowed schemes: http, https, ftp, mailto)';
1092  } elseif (!$this->ID3v2IsValidCOMRreceivedAs($source_data_array['receivedasid'])) {
1093  $this->errors[] = 'Invalid Received As byte in '.$frame_name.' ('.$source_data_array['contacturl'].') (range = 0 to 8)';
1094  } elseif (!$this->IsValidMIMEstring($source_data_array['mime'])) {
1095  $this->errors[] = 'Invalid MIME Type in '.$frame_name.' ('.$source_data_array['mime'].')';
1096  } else {
1097  $framedata .= chr($source_data_array['encodingid']);
1098  unset($pricestring);
1099  foreach ($source_data_array['price'] as $key => $val) {
1100  if ($this->ID3v2IsValidPriceString($key.$val['value'])) {
1101  $pricestrings[] = $key.$val['value'];
1102  } else {
1103  $this->errors[] = 'Invalid Price String in '.$frame_name.' ('.$key.$val['value'].')';
1104  }
1105  }
1106  $framedata .= implode('/', $pricestrings);
1107  $framedata .= $source_data_array['pricevaliduntil'];
1108  $framedata .= str_replace("\x00", '', $source_data_array['contacturl'])."\x00";
1109  $framedata .= chr($source_data_array['receivedasid']);
1110  $framedata .= $source_data_array['sellername'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array['encodingid']);
1111  $framedata .= $source_data_array['description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array['encodingid']);
1112  $framedata .= $source_data_array['mime']."\x00";
1113  $framedata .= $source_data_array['logo'];
1114  }
1115  break;
1116 
1117  case 'ENCR':
1118  // 4.25 ENCR Encryption method registration (ID3v2.3+ only)
1119  // Owner identifier <text string> $00
1120  // Method symbol $xx
1121  // Encryption data <binary data>
1122  if (!$this->IsWithinBitRange($source_data_array['methodsymbol'], 8, false)) {
1123  $this->errors[] = 'Invalid Group Symbol in '.$frame_name.' ('.$source_data_array['methodsymbol'].') (range = 0 to 255)';
1124  } else {
1125  $framedata .= str_replace("\x00", '', $source_data_array['ownerid'])."\x00";
1126  $framedata .= ord($source_data_array['methodsymbol']);
1127  $framedata .= $source_data_array['data'];
1128  }
1129  break;
1130 
1131  case 'GRID':
1132  // 4.26 GRID Group identification registration (ID3v2.3+ only)
1133  // Owner identifier <text string> $00
1134  // Group symbol $xx
1135  // Group dependent data <binary data>
1136  if (!$this->IsWithinBitRange($source_data_array['groupsymbol'], 8, false)) {
1137  $this->errors[] = 'Invalid Group Symbol in '.$frame_name.' ('.$source_data_array['groupsymbol'].') (range = 0 to 255)';
1138  } else {
1139  $framedata .= str_replace("\x00", '', $source_data_array['ownerid'])."\x00";
1140  $framedata .= ord($source_data_array['groupsymbol']);
1141  $framedata .= $source_data_array['data'];
1142  }
1143  break;
1144 
1145  case 'PRIV':
1146  // 4.27 PRIV Private frame (ID3v2.3+ only)
1147  // Owner identifier <text string> $00
1148  // The private data <binary data>
1149  $framedata .= str_replace("\x00", '', $source_data_array['ownerid'])."\x00";
1150  $framedata .= $source_data_array['data'];
1151  break;
1152 
1153  case 'SIGN':
1154  // 4.28 SIGN Signature frame (ID3v2.4+ only)
1155  // Group symbol $xx
1156  // Signature <binary data>
1157  if (!$this->IsWithinBitRange($source_data_array['groupsymbol'], 8, false)) {
1158  $this->errors[] = 'Invalid Group Symbol in '.$frame_name.' ('.$source_data_array['groupsymbol'].') (range = 0 to 255)';
1159  } else {
1160  $framedata .= ord($source_data_array['groupsymbol']);
1161  $framedata .= $source_data_array['data'];
1162  }
1163  break;
1164 
1165  case 'SEEK':
1166  // 4.29 SEEK Seek frame (ID3v2.4+ only)
1167  // Minimum offset to next tag $xx xx xx xx
1168  if (!$this->IsWithinBitRange($source_data_array['data'], 32, false)) {
1169  $this->errors[] = 'Invalid Minimum Offset in '.$frame_name.' ('.$source_data_array['data'].') (range = 0 to 4294967295)';
1170  } else {
1171  $framedata .= Helper::BigEndian2String($source_data_array['data'], 4, false);
1172  }
1173  break;
1174 
1175  case 'ASPI':
1176  // 4.30 ASPI Audio seek point index (ID3v2.4+ only)
1177  // Indexed data start (S) $xx xx xx xx
1178  // Indexed data length (L) $xx xx xx xx
1179  // Number of index points (N) $xx xx
1180  // Bits per index point (b) $xx
1181  // Then for every index point the following data is included:
1182  // Fraction at index (Fi) $xx (xx)
1183  if (!$this->IsWithinBitRange($source_data_array['datastart'], 32, false)) {
1184  $this->errors[] = 'Invalid Indexed Data Start in '.$frame_name.' ('.$source_data_array['datastart'].') (range = 0 to 4294967295)';
1185  } elseif (!$this->IsWithinBitRange($source_data_array['datalength'], 32, false)) {
1186  $this->errors[] = 'Invalid Indexed Data Length in '.$frame_name.' ('.$source_data_array['datalength'].') (range = 0 to 4294967295)';
1187  } elseif (!$this->IsWithinBitRange($source_data_array['indexpoints'], 16, false)) {
1188  $this->errors[] = 'Invalid Number Of Index Points in '.$frame_name.' ('.$source_data_array['indexpoints'].') (range = 0 to 65535)';
1189  } elseif (!$this->IsWithinBitRange($source_data_array['bitsperpoint'], 8, false)) {
1190  $this->errors[] = 'Invalid Bits Per Index Point in '.$frame_name.' ('.$source_data_array['bitsperpoint'].') (range = 0 to 255)';
1191  } elseif ($source_data_array['indexpoints'] != count($source_data_array['indexes'])) {
1192  $this->errors[] = 'Number Of Index Points does not match actual supplied data in '.$frame_name;
1193  } else {
1194  $framedata .= Helper::BigEndian2String($source_data_array['datastart'], 4, false);
1195  $framedata .= Helper::BigEndian2String($source_data_array['datalength'], 4, false);
1196  $framedata .= Helper::BigEndian2String($source_data_array['indexpoints'], 2, false);
1197  $framedata .= Helper::BigEndian2String($source_data_array['bitsperpoint'], 1, false);
1198  foreach ($source_data_array['indexes'] as $key => $val) {
1199  $framedata .= Helper::BigEndian2String($val, ceil($source_data_array['bitsperpoint'] / 8), false);
1200  }
1201  }
1202  break;
1203 
1204  case 'RGAD':
1205  // RGAD Replay Gain Adjustment
1206  // http://privatewww.essex.ac.uk/~djmrob/replaygain/
1207  // Peak Amplitude $xx $xx $xx $xx
1208  // Radio Replay Gain Adjustment %aaabbbcd %dddddddd
1209  // Audiophile Replay Gain Adjustment %aaabbbcd %dddddddd
1210  // a - name code
1211  // b - originator code
1212  // c - sign bit
1213  // d - replay gain adjustment
1214 
1215  if (($source_data_array['track_adjustment'] > 51) || ($source_data_array['track_adjustment'] < -51)) {
1216  $this->errors[] = 'Invalid Track Adjustment in '.$frame_name.' ('.$source_data_array['track_adjustment'].') (range = -51.0 to +51.0)';
1217  } elseif (($source_data_array['album_adjustment'] > 51) || ($source_data_array['album_adjustment'] < -51)) {
1218  $this->errors[] = 'Invalid Album Adjustment in '.$frame_name.' ('.$source_data_array['album_adjustment'].') (range = -51.0 to +51.0)';
1219  } elseif (!$this->ID3v2IsValidRGADname($source_data_array['raw']['track_name'])) {
1220  $this->errors[] = 'Invalid Track Name Code in '.$frame_name.' ('.$source_data_array['raw']['track_name'].') (range = 0 to 2)';
1221  } elseif (!$this->ID3v2IsValidRGADname($source_data_array['raw']['album_name'])) {
1222  $this->errors[] = 'Invalid Album Name Code in '.$frame_name.' ('.$source_data_array['raw']['album_name'].') (range = 0 to 2)';
1223  } elseif (!$this->ID3v2IsValidRGADoriginator($source_data_array['raw']['track_originator'])) {
1224  $this->errors[] = 'Invalid Track Originator Code in '.$frame_name.' ('.$source_data_array['raw']['track_originator'].') (range = 0 to 3)';
1225  } elseif (!$this->ID3v2IsValidRGADoriginator($source_data_array['raw']['album_originator'])) {
1226  $this->errors[] = 'Invalid Album Originator Code in '.$frame_name.' ('.$source_data_array['raw']['album_originator'].') (range = 0 to 3)';
1227  } else {
1228  $framedata .= Helper::Float2String($source_data_array['peakamplitude'], 32);
1229  $framedata .= Helper::RGADgainString($source_data_array['raw']['track_name'], $source_data_array['raw']['track_originator'], $source_data_array['track_adjustment']);
1230  $framedata .= Helper::RGADgainString($source_data_array['raw']['album_name'], $source_data_array['raw']['album_originator'], $source_data_array['album_adjustment']);
1231  }
1232  break;
1233 
1234  default:
1235  if ((($this->majorversion == 2) && (strlen($frame_name) != 3)) || (($this->majorversion > 2) && (strlen($frame_name) != 4))) {
1236  $this->errors[] = 'Invalid frame name "'.$frame_name.'" for ID3v2.'.$this->majorversion;
1237  } elseif ($frame_name{0} == 'T') {
1238  // 4.2. T??? Text information frames
1239  // Text encoding $xx
1240  // Information <text string(s) according to encoding>
1241  $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid);
1242  if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) {
1243  $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion;
1244  } else {
1245  $framedata .= chr($source_data_array['encodingid']);
1246  $framedata .= $source_data_array['data'];
1247  }
1248  } elseif ($frame_name{0} == 'W') {
1249  // 4.3. W??? URL link frames
1250  // URL <text string>
1251  if (!$this->IsValidURL($source_data_array['data'], false, false)) {
1252  //$this->errors[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')';
1253  // probably should be an error, need to rewrite IsValidURL() to handle other encodings
1254  $this->warnings[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')';
1255  } else {
1256  $framedata .= $source_data_array['data'];
1257  }
1258  } else {
1259  $this->errors[] = $frame_name.' not yet supported in $this->GenerateID3v2FrameData()';
1260  }
1261  break;
1262  }
1263  }
1264  if (!empty($this->errors)) {
1265  return false;
1266  }
1267 
1268  return $framedata;
1269  }
static IsValidID3v2FrameName($framename, $id3v2majorversion)
Definition: Id3v2.php:3404
ID3v2IsValidAPICpicturetype($picturetype)
Definition: Id3v2.php:1865
IsWithinBitRange($number, $maxbits, $signed=false)
Definition: Id3v2.php:2066
static Float2String($floatvalue, $bits)
Definition: Helper.php:237
static BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false)
Definition: Helper.php:444
static LanguageLookup($languagecode, $casesensitive=false)
Definition: Id3v2.php:2372
ID3v2IsValidPriceString($pricestring)
Definition: Id3v2.php:1754
ID3v2IsValidCOMRreceivedAs($receivedas)
Definition: Id3v2.php:1901
static Dec2Bin($number)
Definition: Helper.php:472
ID3v2IsValidETCOevent($eventid)
Definition: Id3v2.php:1808
static IsValidDateStampString($datestamp)
Definition: Id3v2.php:3449
ID3v2IsValidTextEncoding($textencodingbyte)
array $ID3v2IsValidTextEncoding_cache
Definition: Id3v2.php:1944
static TextEncodingTerminatorLookup($encoding)
array $TextEncodingTerminatorLookup
Definition: Id3v2.php:3362
ID3v2IsValidRGADname($RGADname)
Definition: Id3v2.php:1915
ID3v2IsValidSYLTtype($contenttype)
Definition: Id3v2.php:1835
static RGADgainString($namecode, $originatorcode, $replaygain)
Definition: Helper.php:1588
IsValidURL($url, $allowUserPass=false)
Definition: Id3v2.php:2105
IsValidMIMEstring($mimestring)
Definition: Id3v2.php:2050
ID3v2IsValidAPICimageformat($imageformat)
Definition: Id3v2.php:1879
static IsANumber($numberstring, $allowdecimal=false, $allownegative=false)
Definition: Id3v2.php:3427
ID3v2IsValidRGADoriginator($RGADoriginator)
Definition: Id3v2.php:1929
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GenerateID3v2FrameFlags()

GetId3\Write\Id3v2::GenerateID3v2FrameFlags (   $TagAlter = false,
  $FileAlter = false,
  $ReadOnly = false,
  $Compression = false,
  $Encryption = false,
  $GroupingIdentity = false,
  $Unsynchronisation = false,
  $DataLengthIndicator = false 
)
Parameters
type$TagAlter
type$FileAlter
type$ReadOnly
type$Compression
type$Encryption
type$GroupingIdentity
type$Unsynchronisation
type$DataLengthIndicator
Returns
boolean

Definition at line 347 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\GenerateID3v2Tag().

348  {
349  switch ($this->majorversion) {
350  case 4:
351  // %0abc0000 %0h00kmnp
352  $flag1 = '0';
353  $flag1 .= $TagAlter ? '1' : '0'; // a - Tag alter preservation (true == discard)
354  $flag1 .= $FileAlter ? '1' : '0'; // b - File alter preservation (true == discard)
355  $flag1 .= $ReadOnly ? '1' : '0'; // c - Read only (true == read only)
356  $flag1 .= '0000';
357 
358  $flag2 = '0';
359  $flag2 .= $GroupingIdentity ? '1' : '0'; // h - Grouping identity (true == contains group information)
360  $flag2 .= '00';
361  $flag2 .= $Compression ? '1' : '0'; // k - Compression (true == compressed)
362  $flag2 .= $Encryption ? '1' : '0'; // m - Encryption (true == encrypted)
363  $flag2 .= $Unsynchronisation ? '1' : '0'; // n - Unsynchronisation (true == unsynchronised)
364  $flag2 .= $DataLengthIndicator ? '1' : '0'; // p - Data length indicator (true == data length indicator added)
365  break;
366 
367  case 3:
368  // %abc00000 %ijk00000
369  $flag1 = $TagAlter ? '1' : '0'; // a - Tag alter preservation (true == discard)
370  $flag1 .= $FileAlter ? '1' : '0'; // b - File alter preservation (true == discard)
371  $flag1 .= $ReadOnly ? '1' : '0'; // c - Read only (true == read only)
372  $flag1 .= '00000';
373 
374  $flag2 = $Compression ? '1' : '0'; // i - Compression (true == compressed)
375  $flag2 .= $Encryption ? '1' : '0'; // j - Encryption (true == encrypted)
376  $flag2 .= $GroupingIdentity ? '1' : '0'; // k - Grouping identity (true == contains group information)
377  $flag2 .= '00000';
378  break;
379 
380  default:
381  return false;
382  break;
383 
384  }
385 
386  return chr(bindec($flag1)).chr(bindec($flag2));
387  }
+ Here is the caller graph for this function:

◆ GenerateID3v2Tag()

GetId3\Write\Id3v2::GenerateID3v2Tag (   $noerrorsonly = true)
Parameters
type$noerrorsonly
Returns
boolean

Definition at line 1636 of file Id3v2.php.

References array, GetId3\Lib\Helper\BigEndian2String(), GetId3\Write\Id3v2\GenerateID3v2FrameData(), GetId3\Write\Id3v2\GenerateID3v2FrameFlags(), GetId3\Write\Id3v2\GenerateID3v2TagFlags(), GetId3\Write\Id3v2\ID3v2FrameFlagsLookupFileAlter(), GetId3\Write\Id3v2\ID3v2FrameFlagsLookupTagAlter(), GetId3\Write\Id3v2\ID3v2FrameIsAllowed(), GetId3\Module\Tag\Id3v2\ID3v2HeaderLength(), GetId3\Module\Tag\Id3v2\IsValidID3v2FrameName(), and GetId3\Write\Id3v2\Unsynchronise().

Referenced by GetId3\Write\Id3v2\WriteID3v2().

1637  {
1638  $this->ID3v2FrameIsAllowed(null, ''); // clear static array in case this isn't the first call to $this->GenerateID3v2Tag()
1639 
1640  $tagstring = '';
1641  if (is_array($this->tag_data)) {
1642  foreach ($this->tag_data as $frame_name => $frame_rawinputdata) {
1643  foreach ($frame_rawinputdata as $irrelevantindex => $source_data_array) {
1644  if (Tag\Id3v2::IsValidID3v2FrameName($frame_name, $this->majorversion)) {
1645  unset($frame_length);
1646  unset($frame_flags);
1647  $frame_data = false;
1648  if ($this->ID3v2FrameIsAllowed($frame_name, $source_data_array)) {
1649  if ($frame_data = $this->GenerateID3v2FrameData($frame_name, $source_data_array)) {
1650  $FrameUnsynchronisation = false;
1651  if ($this->majorversion >= 4) {
1652  // frame-level unsynchronisation
1653  $unsynchdata = $frame_data;
1654  if ($this->id3v2_use_unsynchronisation) {
1655  $unsynchdata = $this->Unsynchronise($frame_data);
1656  }
1657  if (strlen($unsynchdata) != strlen($frame_data)) {
1658  // unsynchronisation needed
1659  $FrameUnsynchronisation = true;
1660  $frame_data = $unsynchdata;
1661  if (isset($TagUnsynchronisation) && $TagUnsynchronisation === false) {
1662  // only set to true if ALL frames are unsynchronised
1663  } else {
1664  $TagUnsynchronisation = true;
1665  }
1666  } else {
1667  if (isset($TagUnsynchronisation)) {
1668  $TagUnsynchronisation = false;
1669  }
1670  }
1671  unset($unsynchdata);
1672 
1673  $frame_length = Helper::BigEndian2String(strlen($frame_data), 4, true);
1674  } else {
1675  $frame_length = Helper::BigEndian2String(strlen($frame_data), 4, false);
1676  }
1677  $frame_flags = $this->GenerateID3v2FrameFlags($this->ID3v2FrameFlagsLookupTagAlter($frame_name), $this->ID3v2FrameFlagsLookupFileAlter($frame_name), false, false, false, false, $FrameUnsynchronisation, false);
1678  }
1679  } else {
1680  $this->errors[] = 'Frame "'.$frame_name.'" is NOT allowed';
1681  }
1682  if ($frame_data === false) {
1683  $this->errors[] = '$this->GenerateID3v2FrameData() failed for "'.$frame_name.'"';
1684  if ($noerrorsonly) {
1685  return false;
1686  } else {
1687  unset($frame_name);
1688  }
1689  }
1690  } else {
1691  // ignore any invalid frame names, including 'title', 'header', etc
1692  $this->warnings[] = 'Ignoring invalid ID3v2 frame type: "'.$frame_name.'"';
1693  unset($frame_name);
1694  unset($frame_length);
1695  unset($frame_flags);
1696  unset($frame_data);
1697  }
1698  if (isset($frame_name) && isset($frame_length) && isset($frame_flags) && isset($frame_data)) {
1699  $tagstring .= $frame_name.$frame_length.$frame_flags.$frame_data;
1700  }
1701  }
1702  }
1703 
1704  if (!isset($TagUnsynchronisation)) {
1705  $TagUnsynchronisation = false;
1706  }
1707  if (($this->majorversion <= 3) && $this->id3v2_use_unsynchronisation) {
1708  // tag-level unsynchronisation
1709  $unsynchdata = $this->Unsynchronise($tagstring);
1710  if (strlen($unsynchdata) != strlen($tagstring)) {
1711  // unsynchronisation needed
1712  $TagUnsynchronisation = true;
1713  $tagstring = $unsynchdata;
1714  }
1715  }
1716 
1717  while ($this->paddedlength < (strlen($tagstring) + Tag\Id3v2::ID3v2HeaderLength($this->majorversion))) {
1718  $this->paddedlength += 1024;
1719  }
1720 
1721  $footer = false; // ID3v2 footers not yet supported in GetId3Core()
1722  if (!$footer && ($this->paddedlength > (strlen($tagstring) + Tag\Id3v2::ID3v2HeaderLength($this->majorversion)))) {
1723  // pad up to $paddedlength bytes if unpadded tag is shorter than $paddedlength
1724  // "Furthermore it MUST NOT have any padding when a tag footer is added to the tag."
1725  if (($this->paddedlength - strlen($tagstring) - Tag\Id3v2::ID3v2HeaderLength($this->majorversion)) > 0) {
1726  $tagstring .= str_repeat("\x00", $this->paddedlength - strlen($tagstring) - Tag\Id3v2::ID3v2HeaderLength($this->majorversion));
1727  }
1728  }
1729  if ($this->id3v2_use_unsynchronisation && (substr($tagstring, strlen($tagstring) - 1, 1) == "\xFF")) {
1730  // special unsynchronisation case:
1731  // if last byte == $FF then appended a $00
1732  $TagUnsynchronisation = true;
1733  $tagstring .= "\x00";
1734  }
1735 
1736  $tagheader = 'ID3';
1737  $tagheader .= chr($this->majorversion);
1738  $tagheader .= chr($this->minorversion);
1739  $tagheader .= $this->GenerateID3v2TagFlags(array('unsynchronisation'=>$TagUnsynchronisation));
1740  $tagheader .= Helper::BigEndian2String(strlen($tagstring), 4, true);
1741 
1742  return $tagheader.$tagstring;
1743  }
1744  $this->errors[] = 'tag_data is not an array in GenerateID3v2Tag()';
1745 
1746  return false;
1747  }
static IsValidID3v2FrameName($framename, $id3v2majorversion)
Definition: Id3v2.php:3404
GenerateID3v2TagFlags($flags)
Definition: Id3v2.php:300
static BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false)
Definition: Helper.php:444
Unsynchronise($data)
Definition: Id3v2.php:1959
ID3v2FrameFlagsLookupFileAlter($framename)
Definition: Id3v2.php:1789
ID3v2FrameFlagsLookupTagAlter($framename)
Definition: Id3v2.php:1770
Create styles array
The data for the language used.
GenerateID3v2FrameFlags($TagAlter=false, $FileAlter=false, $ReadOnly=false, $Compression=false, $Encryption=false, $GroupingIdentity=false, $Unsynchronisation=false, $DataLengthIndicator=false)
Definition: Id3v2.php:347
ID3v2FrameIsAllowed($frame_name, $source_data_array)
Definition: Id3v2.php:1271
GenerateID3v2FrameData($frame_name, $source_data_array)
Definition: Id3v2.php:395
static ID3v2HeaderLength($majorversion)
Definition: Id3v2.php:3484
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GenerateID3v2TagFlags()

GetId3\Write\Id3v2::GenerateID3v2TagFlags (   $flags)
Parameters
type$flags
Returns
boolean

Definition at line 300 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\GenerateID3v2Tag().

301  {
302  switch ($this->majorversion) {
303  case 4:
304  // %abcd0000
305  $flag = (!empty($flags['unsynchronisation']) ? '1' : '0'); // a - Unsynchronisation
306  $flag .= (!empty($flags['extendedheader'] ) ? '1' : '0'); // b - Extended header
307  $flag .= (!empty($flags['experimental'] ) ? '1' : '0'); // c - Experimental indicator
308  $flag .= (!empty($flags['footer'] ) ? '1' : '0'); // d - Footer present
309  $flag .= '0000';
310  break;
311 
312  case 3:
313  // %abc00000
314  $flag = (!empty($flags['unsynchronisation']) ? '1' : '0'); // a - Unsynchronisation
315  $flag .= (!empty($flags['extendedheader'] ) ? '1' : '0'); // b - Extended header
316  $flag .= (!empty($flags['experimental'] ) ? '1' : '0'); // c - Experimental indicator
317  $flag .= '00000';
318  break;
319 
320  case 2:
321  // %ab000000
322  $flag = (!empty($flags['unsynchronisation']) ? '1' : '0'); // a - Unsynchronisation
323  $flag .= (!empty($flags['compression'] ) ? '1' : '0'); // b - Compression
324  $flag .= '000000';
325  break;
326 
327  default:
328  return false;
329  break;
330  }
331 
332  return chr(bindec($flag));
333  }
+ Here is the caller graph for this function:

◆ ID3v2FrameFlagsLookupFileAlter()

GetId3\Write\Id3v2::ID3v2FrameFlagsLookupFileAlter (   $framename)
Parameters
type$framename
Returns
boolean

Definition at line 1789 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\GenerateID3v2Tag().

1790  {
1791  // unfinished
1792  switch ($framename) {
1793  case 'RGAD':
1794  return false;
1795  break;
1796 
1797  default:
1798  return false;
1799  break;
1800  }
1801  }
+ Here is the caller graph for this function:

◆ ID3v2FrameFlagsLookupTagAlter()

GetId3\Write\Id3v2::ID3v2FrameFlagsLookupTagAlter (   $framename)
Parameters
type$framename
Returns
boolean

Definition at line 1770 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\GenerateID3v2Tag().

1771  {
1772  // unfinished
1773  switch ($framename) {
1774  case 'RGAD':
1775  $allow = true;
1776  default:
1777  $allow = false;
1778  break;
1779  }
1780 
1781  return $allow;
1782  }
+ Here is the caller graph for this function:

◆ ID3v2FrameIsAllowed()

GetId3\Write\Id3v2::ID3v2FrameIsAllowed (   $frame_name,
  $source_data_array 
)

Definition at line 1271 of file Id3v2.php.

References array.

Referenced by GetId3\Write\Id3v2\GenerateID3v2Tag().

1272  {
1273  static $PreviousFrames = array();
1274 
1275  if ($frame_name === null) {
1276  // if the writing functions are called multiple times, the static array needs to be
1277  // cleared - this can be done by calling $this->ID3v2FrameIsAllowed(null, '')
1278  $PreviousFrames = array();
1279 
1280  return true;
1281  }
1282 
1283  if ($this->majorversion == 4) {
1284  switch ($frame_name) {
1285  case 'UFID':
1286  case 'AENC':
1287  case 'ENCR':
1288  case 'GRID':
1289  if (!isset($source_data_array['ownerid'])) {
1290  $this->errors[] = '[ownerid] not specified for '.$frame_name;
1291  } elseif (in_array($frame_name.$source_data_array['ownerid'], $PreviousFrames)) {
1292  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same OwnerID ('.$source_data_array['ownerid'].')';
1293  } else {
1294  $PreviousFrames[] = $frame_name.$source_data_array['ownerid'];
1295  }
1296  break;
1297 
1298  case 'TXXX':
1299  case 'WXXX':
1300  case 'RVA2':
1301  case 'EQU2':
1302  case 'APIC':
1303  case 'GEOB':
1304  if (!isset($source_data_array['description'])) {
1305  $this->errors[] = '[description] not specified for '.$frame_name;
1306  } elseif (in_array($frame_name.$source_data_array['description'], $PreviousFrames)) {
1307  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same Description ('.$source_data_array['description'].')';
1308  } else {
1309  $PreviousFrames[] = $frame_name.$source_data_array['description'];
1310  }
1311  break;
1312 
1313  case 'USER':
1314  if (!isset($source_data_array['language'])) {
1315  $this->errors[] = '[language] not specified for '.$frame_name;
1316  } elseif (in_array($frame_name.$source_data_array['language'], $PreviousFrames)) {
1317  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same Language ('.$source_data_array['language'].')';
1318  } else {
1319  $PreviousFrames[] = $frame_name.$source_data_array['language'];
1320  }
1321  break;
1322 
1323  case 'USLT':
1324  case 'SYLT':
1325  case 'COMM':
1326  if (!isset($source_data_array['language'])) {
1327  $this->errors[] = '[language] not specified for '.$frame_name;
1328  } elseif (!isset($source_data_array['description'])) {
1329  $this->errors[] = '[description] not specified for '.$frame_name;
1330  } elseif (in_array($frame_name.$source_data_array['language'].$source_data_array['description'], $PreviousFrames)) {
1331  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same Language + Description ('.$source_data_array['language'].' + '.$source_data_array['description'].')';
1332  } else {
1333  $PreviousFrames[] = $frame_name.$source_data_array['language'].$source_data_array['description'];
1334  }
1335  break;
1336 
1337  case 'POPM':
1338  if (!isset($source_data_array['email'])) {
1339  $this->errors[] = '[email] not specified for '.$frame_name;
1340  } elseif (in_array($frame_name.$source_data_array['email'], $PreviousFrames)) {
1341  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same Email ('.$source_data_array['email'].')';
1342  } else {
1343  $PreviousFrames[] = $frame_name.$source_data_array['email'];
1344  }
1345  break;
1346 
1347  case 'IPLS':
1348  case 'MCDI':
1349  case 'ETCO':
1350  case 'MLLT':
1351  case 'SYTC':
1352  case 'RVRB':
1353  case 'PCNT':
1354  case 'RBUF':
1355  case 'POSS':
1356  case 'OWNE':
1357  case 'SEEK':
1358  case 'ASPI':
1359  case 'RGAD':
1360  if (in_array($frame_name, $PreviousFrames)) {
1361  $this->errors[] = 'Only one '.$frame_name.' tag allowed';
1362  } else {
1363  $PreviousFrames[] = $frame_name;
1364  }
1365  break;
1366 
1367  case 'LINK':
1368  // this isn't implemented quite right (yet) - it should check the target frame data for compliance
1369  // but right now it just allows one linked frame of each type, to be safe.
1370  if (!isset($source_data_array['frameid'])) {
1371  $this->errors[] = '[frameid] not specified for '.$frame_name;
1372  } elseif (in_array($frame_name.$source_data_array['frameid'], $PreviousFrames)) {
1373  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same FrameID ('.$source_data_array['frameid'].')';
1374  } elseif (in_array($source_data_array['frameid'], $PreviousFrames)) {
1375  // no links to singleton tags
1376  $this->errors[] = 'Cannot specify a '.$frame_name.' tag to a singleton tag that already exists ('.$source_data_array['frameid'].')';
1377  } else {
1378  $PreviousFrames[] = $frame_name.$source_data_array['frameid']; // only one linked tag of this type
1379  $PreviousFrames[] = $source_data_array['frameid']; // no non-linked singleton tags of this type
1380  }
1381  break;
1382 
1383  case 'COMR':
1384  // There may be more than one 'commercial frame' in a tag, but no two may be identical
1385  // Checking isn't implemented at all (yet) - just assumes that it's OK.
1386  break;
1387 
1388  case 'PRIV':
1389  case 'SIGN':
1390  if (!isset($source_data_array['ownerid'])) {
1391  $this->errors[] = '[ownerid] not specified for '.$frame_name;
1392  } elseif (!isset($source_data_array['data'])) {
1393  $this->errors[] = '[data] not specified for '.$frame_name;
1394  } elseif (in_array($frame_name.$source_data_array['ownerid'].$source_data_array['data'], $PreviousFrames)) {
1395  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same OwnerID + Data ('.$source_data_array['ownerid'].' + '.$source_data_array['data'].')';
1396  } else {
1397  $PreviousFrames[] = $frame_name.$source_data_array['ownerid'].$source_data_array['data'];
1398  }
1399  break;
1400 
1401  default:
1402  if (($frame_name{0} != 'T') && ($frame_name{0} != 'W')) {
1403  $this->errors[] = 'Frame not allowed in ID3v2.'.$this->majorversion.': '.$frame_name;
1404  }
1405  break;
1406  }
1407 
1408  } elseif ($this->majorversion == 3) {
1409 
1410  switch ($frame_name) {
1411  case 'UFID':
1412  case 'AENC':
1413  case 'ENCR':
1414  case 'GRID':
1415  if (!isset($source_data_array['ownerid'])) {
1416  $this->errors[] = '[ownerid] not specified for '.$frame_name;
1417  } elseif (in_array($frame_name.$source_data_array['ownerid'], $PreviousFrames)) {
1418  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same OwnerID ('.$source_data_array['ownerid'].')';
1419  } else {
1420  $PreviousFrames[] = $frame_name.$source_data_array['ownerid'];
1421  }
1422  break;
1423 
1424  case 'TXXX':
1425  case 'WXXX':
1426  case 'APIC':
1427  case 'GEOB':
1428  if (!isset($source_data_array['description'])) {
1429  $this->errors[] = '[description] not specified for '.$frame_name;
1430  } elseif (in_array($frame_name.$source_data_array['description'], $PreviousFrames)) {
1431  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same Description ('.$source_data_array['description'].')';
1432  } else {
1433  $PreviousFrames[] = $frame_name.$source_data_array['description'];
1434  }
1435  break;
1436 
1437  case 'USER':
1438  if (!isset($source_data_array['language'])) {
1439  $this->errors[] = '[language] not specified for '.$frame_name;
1440  } elseif (in_array($frame_name.$source_data_array['language'], $PreviousFrames)) {
1441  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same Language ('.$source_data_array['language'].')';
1442  } else {
1443  $PreviousFrames[] = $frame_name.$source_data_array['language'];
1444  }
1445  break;
1446 
1447  case 'USLT':
1448  case 'SYLT':
1449  case 'COMM':
1450  if (!isset($source_data_array['language'])) {
1451  $this->errors[] = '[language] not specified for '.$frame_name;
1452  } elseif (!isset($source_data_array['description'])) {
1453  $this->errors[] = '[description] not specified for '.$frame_name;
1454  } elseif (in_array($frame_name.$source_data_array['language'].$source_data_array['description'], $PreviousFrames)) {
1455  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same Language + Description ('.$source_data_array['language'].' + '.$source_data_array['description'].')';
1456  } else {
1457  $PreviousFrames[] = $frame_name.$source_data_array['language'].$source_data_array['description'];
1458  }
1459  break;
1460 
1461  case 'POPM':
1462  if (!isset($source_data_array['email'])) {
1463  $this->errors[] = '[email] not specified for '.$frame_name;
1464  } elseif (in_array($frame_name.$source_data_array['email'], $PreviousFrames)) {
1465  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same Email ('.$source_data_array['email'].')';
1466  } else {
1467  $PreviousFrames[] = $frame_name.$source_data_array['email'];
1468  }
1469  break;
1470 
1471  case 'IPLS':
1472  case 'MCDI':
1473  case 'ETCO':
1474  case 'MLLT':
1475  case 'SYTC':
1476  case 'RVAD':
1477  case 'EQUA':
1478  case 'RVRB':
1479  case 'PCNT':
1480  case 'RBUF':
1481  case 'POSS':
1482  case 'OWNE':
1483  case 'RGAD':
1484  if (in_array($frame_name, $PreviousFrames)) {
1485  $this->errors[] = 'Only one '.$frame_name.' tag allowed';
1486  } else {
1487  $PreviousFrames[] = $frame_name;
1488  }
1489  break;
1490 
1491  case 'LINK':
1492  // this isn't implemented quite right (yet) - it should check the target frame data for compliance
1493  // but right now it just allows one linked frame of each type, to be safe.
1494  if (!isset($source_data_array['frameid'])) {
1495  $this->errors[] = '[frameid] not specified for '.$frame_name;
1496  } elseif (in_array($frame_name.$source_data_array['frameid'], $PreviousFrames)) {
1497  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same FrameID ('.$source_data_array['frameid'].')';
1498  } elseif (in_array($source_data_array['frameid'], $PreviousFrames)) {
1499  // no links to singleton tags
1500  $this->errors[] = 'Cannot specify a '.$frame_name.' tag to a singleton tag that already exists ('.$source_data_array['frameid'].')';
1501  } else {
1502  $PreviousFrames[] = $frame_name.$source_data_array['frameid']; // only one linked tag of this type
1503  $PreviousFrames[] = $source_data_array['frameid']; // no non-linked singleton tags of this type
1504  }
1505  break;
1506 
1507  case 'COMR':
1508  // There may be more than one 'commercial frame' in a tag, but no two may be identical
1509  // Checking isn't implemented at all (yet) - just assumes that it's OK.
1510  break;
1511 
1512  case 'PRIV':
1513  if (!isset($source_data_array['ownerid'])) {
1514  $this->errors[] = '[ownerid] not specified for '.$frame_name;
1515  } elseif (!isset($source_data_array['data'])) {
1516  $this->errors[] = '[data] not specified for '.$frame_name;
1517  } elseif (in_array($frame_name.$source_data_array['ownerid'].$source_data_array['data'], $PreviousFrames)) {
1518  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same OwnerID + Data ('.$source_data_array['ownerid'].' + '.$source_data_array['data'].')';
1519  } else {
1520  $PreviousFrames[] = $frame_name.$source_data_array['ownerid'].$source_data_array['data'];
1521  }
1522  break;
1523 
1524  default:
1525  if (($frame_name{0} != 'T') && ($frame_name{0} != 'W')) {
1526  $this->errors[] = 'Frame not allowed in ID3v2.'.$this->majorversion.': '.$frame_name;
1527  }
1528  break;
1529  }
1530 
1531  } elseif ($this->majorversion == 2) {
1532 
1533  switch ($frame_name) {
1534  case 'UFI':
1535  case 'CRM':
1536  case 'CRA':
1537  if (!isset($source_data_array['ownerid'])) {
1538  $this->errors[] = '[ownerid] not specified for '.$frame_name;
1539  } elseif (in_array($frame_name.$source_data_array['ownerid'], $PreviousFrames)) {
1540  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same OwnerID ('.$source_data_array['ownerid'].')';
1541  } else {
1542  $PreviousFrames[] = $frame_name.$source_data_array['ownerid'];
1543  }
1544  break;
1545 
1546  case 'TXX':
1547  case 'WXX':
1548  case 'PIC':
1549  case 'GEO':
1550  if (!isset($source_data_array['description'])) {
1551  $this->errors[] = '[description] not specified for '.$frame_name;
1552  } elseif (in_array($frame_name.$source_data_array['description'], $PreviousFrames)) {
1553  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same Description ('.$source_data_array['description'].')';
1554  } else {
1555  $PreviousFrames[] = $frame_name.$source_data_array['description'];
1556  }
1557  break;
1558 
1559  case 'ULT':
1560  case 'SLT':
1561  case 'COM':
1562  if (!isset($source_data_array['language'])) {
1563  $this->errors[] = '[language] not specified for '.$frame_name;
1564  } elseif (!isset($source_data_array['description'])) {
1565  $this->errors[] = '[description] not specified for '.$frame_name;
1566  } elseif (in_array($frame_name.$source_data_array['language'].$source_data_array['description'], $PreviousFrames)) {
1567  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same Language + Description ('.$source_data_array['language'].' + '.$source_data_array['description'].')';
1568  } else {
1569  $PreviousFrames[] = $frame_name.$source_data_array['language'].$source_data_array['description'];
1570  }
1571  break;
1572 
1573  case 'POP':
1574  if (!isset($source_data_array['email'])) {
1575  $this->errors[] = '[email] not specified for '.$frame_name;
1576  } elseif (in_array($frame_name.$source_data_array['email'], $PreviousFrames)) {
1577  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same Email ('.$source_data_array['email'].')';
1578  } else {
1579  $PreviousFrames[] = $frame_name.$source_data_array['email'];
1580  }
1581  break;
1582 
1583  case 'IPL':
1584  case 'MCI':
1585  case 'ETC':
1586  case 'MLL':
1587  case 'STC':
1588  case 'RVA':
1589  case 'EQU':
1590  case 'REV':
1591  case 'CNT':
1592  case 'BUF':
1593  if (in_array($frame_name, $PreviousFrames)) {
1594  $this->errors[] = 'Only one '.$frame_name.' tag allowed';
1595  } else {
1596  $PreviousFrames[] = $frame_name;
1597  }
1598  break;
1599 
1600  case 'LNK':
1601  // this isn't implemented quite right (yet) - it should check the target frame data for compliance
1602  // but right now it just allows one linked frame of each type, to be safe.
1603  if (!isset($source_data_array['frameid'])) {
1604  $this->errors[] = '[frameid] not specified for '.$frame_name;
1605  } elseif (in_array($frame_name.$source_data_array['frameid'], $PreviousFrames)) {
1606  $this->errors[] = 'Only one '.$frame_name.' tag allowed with the same FrameID ('.$source_data_array['frameid'].')';
1607  } elseif (in_array($source_data_array['frameid'], $PreviousFrames)) {
1608  // no links to singleton tags
1609  $this->errors[] = 'Cannot specify a '.$frame_name.' tag to a singleton tag that already exists ('.$source_data_array['frameid'].')';
1610  } else {
1611  $PreviousFrames[] = $frame_name.$source_data_array['frameid']; // only one linked tag of this type
1612  $PreviousFrames[] = $source_data_array['frameid']; // no non-linked singleton tags of this type
1613  }
1614  break;
1615 
1616  default:
1617  if (($frame_name{0} != 'T') && ($frame_name{0} != 'W')) {
1618  $this->errors[] = 'Frame not allowed in ID3v2.'.$this->majorversion.': '.$frame_name;
1619  }
1620  break;
1621  }
1622  }
1623 
1624  if (!empty($this->errors)) {
1625  return false;
1626  }
1627 
1628  return true;
1629  }
Create styles array
The data for the language used.
+ Here is the caller graph for this function:

◆ ID3v2IsValidAPICimageformat()

GetId3\Write\Id3v2::ID3v2IsValidAPICimageformat (   $imageformat)
Parameters
type$imageformat
Returns
boolean

Definition at line 1879 of file Id3v2.php.

References GetId3\Write\Id3v2\IsValidMIMEstring().

Referenced by GetId3\Write\Id3v2\GenerateID3v2FrameData().

1880  {
1881  if ($imageformat == '-->') {
1882  return true;
1883  } elseif ($this->majorversion == 2) {
1884  if ((strlen($imageformat) == 3) && ($imageformat == strtoupper($imageformat))) {
1885  return true;
1886  }
1887  } elseif (($this->majorversion == 3) || ($this->majorversion == 4)) {
1888  if ($this->IsValidMIMEstring($imageformat)) {
1889  return true;
1890  }
1891  }
1892 
1893  return false;
1894  }
IsValidMIMEstring($mimestring)
Definition: Id3v2.php:2050
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ID3v2IsValidAPICpicturetype()

GetId3\Write\Id3v2::ID3v2IsValidAPICpicturetype (   $picturetype)
Parameters
type$picturetype
Returns
boolean

Definition at line 1865 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\GenerateID3v2FrameData().

1866  {
1867  if (($picturetype >= 0) && ($picturetype <= 0x14) && ($this->majorversion >= 2) && ($this->majorversion <= 4)) {
1868  return true;
1869  }
1870 
1871  return false;
1872  }
+ Here is the caller graph for this function:

◆ ID3v2IsValidCOMRreceivedAs()

GetId3\Write\Id3v2::ID3v2IsValidCOMRreceivedAs (   $receivedas)
Parameters
type$receivedas
Returns
boolean

Definition at line 1901 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\GenerateID3v2FrameData().

1902  {
1903  if (($this->majorversion >= 3) && ($receivedas >= 0) && ($receivedas <= 8)) {
1904  return true;
1905  }
1906 
1907  return false;
1908  }
+ Here is the caller graph for this function:

◆ ID3v2IsValidETCOevent()

GetId3\Write\Id3v2::ID3v2IsValidETCOevent (   $eventid)
Parameters
type$eventid
Returns
boolean

Definition at line 1808 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\GenerateID3v2FrameData().

1809  {
1810  if (($eventid < 0) || ($eventid > 0xFF)) {
1811  // outside range of 1 byte
1812  return false;
1813  } elseif (($eventid >= 0xF0) && ($eventid <= 0xFC)) {
1814  // reserved for future use
1815  return false;
1816  } elseif (($eventid >= 0x17) && ($eventid <= 0xDF)) {
1817  // reserved for future use
1818  return false;
1819  } elseif (($eventid >= 0x0E) && ($eventid <= 0x16) && ($this->majorversion == 2)) {
1820  // not defined in ID3v2.2
1821  return false;
1822  } elseif (($eventid >= 0x15) && ($eventid <= 0x16) && ($this->majorversion == 3)) {
1823  // not defined in ID3v2.3
1824  return false;
1825  }
1826 
1827  return true;
1828  }
+ Here is the caller graph for this function:

◆ ID3v2IsValidPriceString()

GetId3\Write\Id3v2::ID3v2IsValidPriceString (   $pricestring)
Parameters
type$pricestring
Returns
boolean

Definition at line 1754 of file Id3v2.php.

References GetId3\Module\Tag\Id3v2\IsANumber(), and GetId3\Module\Tag\Id3v2\LanguageLookup().

Referenced by GetId3\Write\Id3v2\GenerateID3v2FrameData().

1755  {
1756  if (Tag\Id3v2::LanguageLookup(substr($pricestring, 0, 3), true) == '') {
1757  return false;
1758  } elseif (!$this->IsANumber(substr($pricestring, 3), true)) {
1759  return false;
1760  }
1761 
1762  return true;
1763  }
static LanguageLookup($languagecode, $casesensitive=false)
Definition: Id3v2.php:2372
static IsANumber($numberstring, $allowdecimal=false, $allownegative=false)
Definition: Id3v2.php:3427
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ID3v2IsValidRGADname()

GetId3\Write\Id3v2::ID3v2IsValidRGADname (   $RGADname)
Parameters
type$RGADname
Returns
boolean

Definition at line 1915 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\GenerateID3v2FrameData().

1916  {
1917  if (($RGADname >= 0) && ($RGADname <= 2)) {
1918  return true;
1919  }
1920 
1921  return false;
1922  }
+ Here is the caller graph for this function:

◆ ID3v2IsValidRGADoriginator()

GetId3\Write\Id3v2::ID3v2IsValidRGADoriginator (   $RGADoriginator)
Parameters
type$RGADoriginator
Returns
boolean

Definition at line 1929 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\GenerateID3v2FrameData().

1930  {
1931  if (($RGADoriginator >= 0) && ($RGADoriginator <= 3)) {
1932  return true;
1933  }
1934 
1935  return false;
1936  }
+ Here is the caller graph for this function:

◆ ID3v2IsValidRVA2channeltype()

GetId3\Write\Id3v2::ID3v2IsValidRVA2channeltype (   $channeltype)
Parameters
type$channeltype
Returns
boolean

Definition at line 1851 of file Id3v2.php.

1852  {
1853  if (($channeltype >= 0) && ($channeltype <= 8) && ($this->majorversion == 4)) {
1854  return true;
1855  }
1856 
1857  return false;
1858  }

◆ ID3v2IsValidSYLTtype()

GetId3\Write\Id3v2::ID3v2IsValidSYLTtype (   $contenttype)
Parameters
type$contenttype
Returns
boolean

Definition at line 1835 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\GenerateID3v2FrameData().

1836  {
1837  if (($contenttype >= 0) && ($contenttype <= 8) && ($this->majorversion == 4)) {
1838  return true;
1839  } elseif (($contenttype >= 0) && ($contenttype <= 6) && ($this->majorversion == 3)) {
1840  return true;
1841  }
1842 
1843  return false;
1844  }
+ Here is the caller graph for this function:

◆ ID3v2IsValidTextEncoding()

GetId3\Write\Id3v2::ID3v2IsValidTextEncoding (   $textencodingbyte)

array $ID3v2IsValidTextEncoding_cache

Parameters
type$textencodingbyte
Returns
type

Definition at line 1944 of file Id3v2.php.

References array.

Referenced by GetId3\Write\Id3v2\GenerateID3v2FrameData().

1945  {
1946  static $ID3v2IsValidTextEncoding_cache = array(
1947  2 => array(true, true),
1948  3 => array(true, true),
1949  4 => array(true, true, true, true));
1950 
1951  return isset($ID3v2IsValidTextEncoding_cache[$this->majorversion][$textencodingbyte]);
1952  }
Create styles array
The data for the language used.
+ Here is the caller graph for this function:

◆ ID3v2ShortFrameNameLookup()

static GetId3\Write\Id3v2::ID3v2ShortFrameNameLookup (   $majorversion,
  $long_description 
)
static

array $ID3v2ShortFrameNameLookup

Parameters
type$majorversion
type$long_description
Returns
type

Definition at line 2145 of file Id3v2.php.

References GetId3\Write\Id3v2\$majorversion, and array.

2146  {
2147  $long_description = str_replace(' ', '_', strtolower(trim($long_description)));
2148  static $ID3v2ShortFrameNameLookup = array();
2149  if (empty($ID3v2ShortFrameNameLookup)) {
2150 
2151  // The following are unique to ID3v2.2
2152  $ID3v2ShortFrameNameLookup[2]['comment'] = 'COM';
2153  $ID3v2ShortFrameNameLookup[2]['album'] = 'TAL';
2154  $ID3v2ShortFrameNameLookup[2]['beats_per_minute'] = 'TBP';
2155  $ID3v2ShortFrameNameLookup[2]['composer'] = 'TCM';
2156  $ID3v2ShortFrameNameLookup[2]['genre'] = 'TCO';
2157  $ID3v2ShortFrameNameLookup[2]['itunescompilation'] = 'TCP';
2158  $ID3v2ShortFrameNameLookup[2]['copyright'] = 'TCR';
2159  $ID3v2ShortFrameNameLookup[2]['encoded_by'] = 'TEN';
2160  $ID3v2ShortFrameNameLookup[2]['language'] = 'TLA';
2161  $ID3v2ShortFrameNameLookup[2]['length'] = 'TLE';
2162  $ID3v2ShortFrameNameLookup[2]['original_artist'] = 'TOA';
2163  $ID3v2ShortFrameNameLookup[2]['original_filename'] = 'TOF';
2164  $ID3v2ShortFrameNameLookup[2]['original_lyricist'] = 'TOL';
2165  $ID3v2ShortFrameNameLookup[2]['original_album_title'] = 'TOT';
2166  $ID3v2ShortFrameNameLookup[2]['artist'] = 'TP1';
2167  $ID3v2ShortFrameNameLookup[2]['band'] = 'TP2';
2168  $ID3v2ShortFrameNameLookup[2]['conductor'] = 'TP3';
2169  $ID3v2ShortFrameNameLookup[2]['remixer'] = 'TP4';
2170  $ID3v2ShortFrameNameLookup[2]['publisher'] = 'TPB';
2171  $ID3v2ShortFrameNameLookup[2]['isrc'] = 'TRC';
2172  $ID3v2ShortFrameNameLookup[2]['tracknumber'] = 'TRK';
2173  $ID3v2ShortFrameNameLookup[2]['size'] = 'TSI';
2174  $ID3v2ShortFrameNameLookup[2]['encoder_settings'] = 'TSS';
2175  $ID3v2ShortFrameNameLookup[2]['description'] = 'TT1';
2176  $ID3v2ShortFrameNameLookup[2]['title'] = 'TT2';
2177  $ID3v2ShortFrameNameLookup[2]['subtitle'] = 'TT3';
2178  $ID3v2ShortFrameNameLookup[2]['lyricist'] = 'TXT';
2179  $ID3v2ShortFrameNameLookup[2]['user_text'] = 'TXX';
2180  $ID3v2ShortFrameNameLookup[2]['year'] = 'TYE';
2181  $ID3v2ShortFrameNameLookup[2]['unique_file_identifier'] = 'UFI';
2182  $ID3v2ShortFrameNameLookup[2]['unsynchronised_lyrics'] = 'ULT';
2183  $ID3v2ShortFrameNameLookup[2]['url_file'] = 'WAF';
2184  $ID3v2ShortFrameNameLookup[2]['url_artist'] = 'WAR';
2185  $ID3v2ShortFrameNameLookup[2]['url_source'] = 'WAS';
2186  $ID3v2ShortFrameNameLookup[2]['copyright_information'] = 'WCP';
2187  $ID3v2ShortFrameNameLookup[2]['url_publisher'] = 'WPB';
2188  $ID3v2ShortFrameNameLookup[2]['url_user'] = 'WXX';
2189 
2190  // The following are common to ID3v2.3 and ID3v2.4
2191  $ID3v2ShortFrameNameLookup[3]['audio_encryption'] = 'AENC';
2192  $ID3v2ShortFrameNameLookup[3]['attached_picture'] = 'APIC';
2193  $ID3v2ShortFrameNameLookup[3]['comment'] = 'COMM';
2194  $ID3v2ShortFrameNameLookup[3]['commercial'] = 'COMR';
2195  $ID3v2ShortFrameNameLookup[3]['encryption_method_registration'] = 'ENCR';
2196  $ID3v2ShortFrameNameLookup[3]['event_timing_codes'] = 'ETCO';
2197  $ID3v2ShortFrameNameLookup[3]['general_encapsulated_object'] = 'GEOB';
2198  $ID3v2ShortFrameNameLookup[3]['group_identification_registration'] = 'GRID';
2199  $ID3v2ShortFrameNameLookup[3]['linked_information'] = 'LINK';
2200  $ID3v2ShortFrameNameLookup[3]['music_cd_identifier'] = 'MCDI';
2201  $ID3v2ShortFrameNameLookup[3]['mpeg_location_lookup_table'] = 'MLLT';
2202  $ID3v2ShortFrameNameLookup[3]['ownership'] = 'OWNE';
2203  $ID3v2ShortFrameNameLookup[3]['play_counter'] = 'PCNT';
2204  $ID3v2ShortFrameNameLookup[3]['popularimeter'] = 'POPM';
2205  $ID3v2ShortFrameNameLookup[3]['position_synchronisation'] = 'POSS';
2206  $ID3v2ShortFrameNameLookup[3]['private'] = 'PRIV';
2207  $ID3v2ShortFrameNameLookup[3]['recommended_buffer_size'] = 'RBUF';
2208  $ID3v2ShortFrameNameLookup[3]['reverb'] = 'RVRB';
2209  $ID3v2ShortFrameNameLookup[3]['synchronised_lyrics'] = 'SYLT';
2210  $ID3v2ShortFrameNameLookup[3]['synchronised_tempo_codes'] = 'SYTC';
2211  $ID3v2ShortFrameNameLookup[3]['album'] = 'TALB';
2212  $ID3v2ShortFrameNameLookup[3]['beats_per_minute'] = 'TBPM';
2213  $ID3v2ShortFrameNameLookup[3]['itunescompilation'] = 'TCMP';
2214  $ID3v2ShortFrameNameLookup[3]['composer'] = 'TCOM';
2215  $ID3v2ShortFrameNameLookup[3]['genre'] = 'TCON';
2216  $ID3v2ShortFrameNameLookup[3]['copyright'] = 'TCOP';
2217  $ID3v2ShortFrameNameLookup[3]['playlist_delay'] = 'TDLY';
2218  $ID3v2ShortFrameNameLookup[3]['encoded_by'] = 'TENC';
2219  $ID3v2ShortFrameNameLookup[3]['lyricist'] = 'TEXT';
2220  $ID3v2ShortFrameNameLookup[3]['file_type'] = 'TFLT';
2221  $ID3v2ShortFrameNameLookup[3]['content_group_description'] = 'TIT1';
2222  $ID3v2ShortFrameNameLookup[3]['title'] = 'TIT2';
2223  $ID3v2ShortFrameNameLookup[3]['subtitle'] = 'TIT3';
2224  $ID3v2ShortFrameNameLookup[3]['initial_key'] = 'TKEY';
2225  $ID3v2ShortFrameNameLookup[3]['language'] = 'TLAN';
2226  $ID3v2ShortFrameNameLookup[3]['length'] = 'TLEN';
2227  $ID3v2ShortFrameNameLookup[3]['media_type'] = 'TMED';
2228  $ID3v2ShortFrameNameLookup[3]['original_album_title'] = 'TOAL';
2229  $ID3v2ShortFrameNameLookup[3]['original_filename'] = 'TOFN';
2230  $ID3v2ShortFrameNameLookup[3]['original_lyricist'] = 'TOLY';
2231  $ID3v2ShortFrameNameLookup[3]['original_artist'] = 'TOPE';
2232  $ID3v2ShortFrameNameLookup[3]['file_owner'] = 'TOWN';
2233  $ID3v2ShortFrameNameLookup[3]['artist'] = 'TPE1';
2234  $ID3v2ShortFrameNameLookup[3]['band'] = 'TPE2';
2235  $ID3v2ShortFrameNameLookup[3]['conductor'] = 'TPE3';
2236  $ID3v2ShortFrameNameLookup[3]['remixer'] = 'TPE4';
2237  $ID3v2ShortFrameNameLookup[3]['part_of_a_set'] = 'TPOS';
2238  $ID3v2ShortFrameNameLookup[3]['publisher'] = 'TPUB';
2239  $ID3v2ShortFrameNameLookup[3]['tracknumber'] = 'TRCK';
2240  $ID3v2ShortFrameNameLookup[3]['internet_radio_station_name'] = 'TRSN';
2241  $ID3v2ShortFrameNameLookup[3]['internet_radio_station_owner'] = 'TRSO';
2242  $ID3v2ShortFrameNameLookup[3]['isrc'] = 'TSRC';
2243  $ID3v2ShortFrameNameLookup[3]['encoder_settings'] = 'TSSE';
2244  $ID3v2ShortFrameNameLookup[3]['user_text'] = 'TXXX';
2245  $ID3v2ShortFrameNameLookup[3]['unique_file_identifier'] = 'UFID';
2246  $ID3v2ShortFrameNameLookup[3]['terms_of_use'] = 'USER';
2247  $ID3v2ShortFrameNameLookup[3]['unsynchronised_lyrics'] = 'USLT';
2248  $ID3v2ShortFrameNameLookup[3]['commercial'] = 'WCOM';
2249  $ID3v2ShortFrameNameLookup[3]['copyright_information'] = 'WCOP';
2250  $ID3v2ShortFrameNameLookup[3]['url_file'] = 'WOAF';
2251  $ID3v2ShortFrameNameLookup[3]['url_artist'] = 'WOAR';
2252  $ID3v2ShortFrameNameLookup[3]['url_source'] = 'WOAS';
2253  $ID3v2ShortFrameNameLookup[3]['url_station'] = 'WORS';
2254  $ID3v2ShortFrameNameLookup[3]['payment'] = 'WPAY';
2255  $ID3v2ShortFrameNameLookup[3]['url_publisher'] = 'WPUB';
2256  $ID3v2ShortFrameNameLookup[3]['url_user'] = 'WXXX';
2257 
2258  // The above are common to ID3v2.3 and ID3v2.4
2259  // so copy them to ID3v2.4 before adding specifics for 2.3 and 2.4
2260  $ID3v2ShortFrameNameLookup[4] = $ID3v2ShortFrameNameLookup[3];
2261 
2262  // The following are unique to ID3v2.3
2263  $ID3v2ShortFrameNameLookup[3]['equalisation'] = 'EQUA';
2264  $ID3v2ShortFrameNameLookup[3]['involved_people_list'] = 'IPLS';
2265  $ID3v2ShortFrameNameLookup[3]['relative_volume_adjustment'] = 'RVAD';
2266  $ID3v2ShortFrameNameLookup[3]['date'] = 'TDAT';
2267  $ID3v2ShortFrameNameLookup[3]['time'] = 'TIME';
2268  $ID3v2ShortFrameNameLookup[3]['original_release_year'] = 'TORY';
2269  $ID3v2ShortFrameNameLookup[3]['recording_dates'] = 'TRDA';
2270  $ID3v2ShortFrameNameLookup[3]['size'] = 'TSIZ';
2271  $ID3v2ShortFrameNameLookup[3]['year'] = 'TYER';
2272 
2273  // The following are unique to ID3v2.4
2274  $ID3v2ShortFrameNameLookup[4]['audio_seek_point_index'] = 'ASPI';
2275  $ID3v2ShortFrameNameLookup[4]['equalisation'] = 'EQU2';
2276  $ID3v2ShortFrameNameLookup[4]['relative_volume_adjustment'] = 'RVA2';
2277  $ID3v2ShortFrameNameLookup[4]['seek'] = 'SEEK';
2278  $ID3v2ShortFrameNameLookup[4]['signature'] = 'SIGN';
2279  $ID3v2ShortFrameNameLookup[4]['encoding_time'] = 'TDEN';
2280  $ID3v2ShortFrameNameLookup[4]['original_release_time'] = 'TDOR';
2281  $ID3v2ShortFrameNameLookup[4]['recording_time'] = 'TDRC';
2282  $ID3v2ShortFrameNameLookup[4]['release_time'] = 'TDRL';
2283  $ID3v2ShortFrameNameLookup[4]['tagging_time'] = 'TDTG';
2284  $ID3v2ShortFrameNameLookup[4]['involved_people_list'] = 'TIPL';
2285  $ID3v2ShortFrameNameLookup[4]['musician_credits_list'] = 'TMCL';
2286  $ID3v2ShortFrameNameLookup[4]['mood'] = 'TMOO';
2287  $ID3v2ShortFrameNameLookup[4]['produced_notice'] = 'TPRO';
2288  $ID3v2ShortFrameNameLookup[4]['album_sort_order'] = 'TSOA';
2289  $ID3v2ShortFrameNameLookup[4]['performer_sort_order'] = 'TSOP';
2290  $ID3v2ShortFrameNameLookup[4]['title_sort_order'] = 'TSOT';
2291  $ID3v2ShortFrameNameLookup[4]['set_subtitle'] = 'TSST';
2292  }
2293 
2294  return (isset($ID3v2ShortFrameNameLookup[$majorversion][strtolower($long_description)]) ? $ID3v2ShortFrameNameLookup[$majorversion][strtolower($long_description)] : '');
2295 
2296  }
Create styles array
The data for the language used.

◆ is_hash()

GetId3\Write\Id3v2::is_hash (   $var)
Parameters
type$var
Returns
boolean

Definition at line 1996 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\array_join_merge().

1997  {
1998  // written by dev-nullØchristophe*vg
1999  // taken from http://www.php.net/manual/en/function.array-merge-recursive.php
2000  if (is_array($var)) {
2001  $keys = array_keys($var);
2002  $all_num = true;
2003  for ($i = 0; $i < count($keys); $i++) {
2004  if (is_string($keys[$i])) {
2005  return true;
2006  }
2007  }
2008  }
2009 
2010  return false;
2011  }
+ Here is the caller graph for this function:

◆ IsValidMIMEstring()

GetId3\Write\Id3v2::IsValidMIMEstring (   $mimestring)
Parameters
type$mimestring
Returns
boolean

Definition at line 2050 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\GenerateID3v2FrameData(), and GetId3\Write\Id3v2\ID3v2IsValidAPICimageformat().

2051  {
2052  if ((strlen($mimestring) >= 3) && (strpos($mimestring, '/') > 0) && (strpos($mimestring, '/') < (strlen($mimestring) - 1))) {
2053  return true;
2054  }
2055 
2056  return false;
2057  }
+ Here is the caller graph for this function:

◆ IsValidURL()

GetId3\Write\Id3v2::IsValidURL (   $url,
  $allowUserPass = false 
)
Parameters
type$url
type$allowUserPass
Returns
boolean

Definition at line 2105 of file Id3v2.php.

References $url, and GetId3\Write\Id3v2\safe_parse_url().

Referenced by GetId3\Write\Id3v2\GenerateID3v2FrameData().

2106  {
2107  if ($url == '') {
2108  return false;
2109  }
2110  if ($allowUserPass !== true) {
2111  if (strstr($url, '@')) {
2112  // in the format http://user:pass@example.com or http://user@example.com
2113  // but could easily be somebody incorrectly entering an email address in place of a URL
2114  return false;
2115  }
2116  }
2117  if ($parts = $this->safe_parse_url($url)) {
2118  if (($parts['scheme'] != 'http') && ($parts['scheme'] != 'https') && ($parts['scheme'] != 'ftp') && ($parts['scheme'] != 'gopher')) {
2119  return false;
2120  } elseif (!preg_match('#^[[:alnum:]]([-.]?[0-9a-z])*\\.[a-z]{2,3}$#i', $parts['host'], $regs) && !preg_match('#^[0-9]{1,3}(\\.[0-9]{1,3}){3}$#', $parts['host'])) {
2121  return false;
2122  } elseif (!preg_match('#^([[:alnum:]-]|[\\_])*$#i', $parts['user'], $regs)) {
2123  return false;
2124  } elseif (!preg_match('#^([[:alnum:]-]|[\\_])*$#i', $parts['pass'], $regs)) {
2125  return false;
2126  } elseif (!preg_match('#^[[:alnum:]/_\\.@~-]*$#i', $parts['path'], $regs)) {
2127  return false;
2128  } elseif (!empty($parts['query']) && !preg_match('#^[[:alnum:]?&=+:;_()%\\#/,\\.-]*$#i', $parts['query'], $regs)) {
2129  return false;
2130  } else {
2131  return true;
2132  }
2133  }
2134 
2135  return false;
2136  }
$url
Definition: shib_logout.php:72
safe_parse_url($url)
Definition: Id3v2.php:2086
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ IsWithinBitRange()

GetId3\Write\Id3v2::IsWithinBitRange (   $number,
  $maxbits,
  $signed = false 
)
Parameters
type$number
type$maxbits
type$signed
Returns
boolean

Definition at line 2066 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\GenerateID3v2FrameData().

2067  {
2068  if ($signed) {
2069  if (($number > (0 - pow(2, $maxbits - 1))) && ($number <= pow(2, $maxbits - 1))) {
2070  return true;
2071  }
2072  } else {
2073  if (($number >= 0) && ($number <= pow(2, $maxbits))) {
2074  return true;
2075  }
2076  }
2077 
2078  return false;
2079  }
+ Here is the caller graph for this function:

◆ RemoveID3v2()

GetId3\Write\Id3v2::RemoveID3v2 ( )

Definition at line 200 of file Id3v2.php.

References GetId3\Handler\BaseHandler\fread(), GetId3\Handler\BaseHandler\fseek(), and GetId3\Lib\Helper\intValueSupported().

201  {
202  // File MUST be writeable - CHMOD(646) at least. It's best if the
203  // directory is also writeable, because that method is both faster and less susceptible to errors.
204  if (is_writeable(dirname($this->filename))) {
205 
206  // preferred method - only one copying operation, minimal chance of corrupting
207  // original file if script is interrupted, but required directory to be writeable
208  if (is_readable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'rb'))) {
209 
210  // Initialize GetId3 engine
211  $getID3 = new GetId3Core();
212  $OldThisFileInfo = $getID3->analyze($this->filename);
213  if (!Helper::intValueSupported($OldThisFileInfo['filesize'])) {
214  $this->errors[] = 'Unable to remove ID3v2 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
215  fclose($fp_source);
216 
217  return false;
218  }
219  rewind($fp_source);
220  if ($OldThisFileInfo['avdataoffset'] !== false) {
221  fseek($fp_source, $OldThisFileInfo['avdataoffset'], SEEK_SET);
222  }
223  if (is_writable($this->filename) && is_file($this->filename) && ($fp_temp = fopen($this->filename.'getid3tmp', 'w+b'))) {
224  while ($buffer = fread($fp_source, $this->fread_buffer_size)) {
225  fwrite($fp_temp, $buffer, strlen($buffer));
226  }
227  fclose($fp_temp);
228  } else {
229  $this->errors[] = 'Could not fopen("'.$this->filename.'getid3tmp", "w+b")';
230  }
231  fclose($fp_source);
232  } else {
233  $this->errors[] = 'Could not fopen("'.$this->filename.'", "rb")';
234  }
235  if (file_exists($this->filename)) {
236  unlink($this->filename);
237  }
238  rename($this->filename.'getid3tmp', $this->filename);
239 
240  } elseif (is_writable($this->filename)) {
241 
242  // less desirable alternate method - double-copies the file, overwrites original file
243  // and could corrupt source file if the script is interrupted or an error occurs.
244  if (is_readable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'rb'))) {
245 
246  // Initialize GetId3 engine
247  $getID3 = new GetId3Core();
248  $OldThisFileInfo = $getID3->analyze($this->filename);
249  if (!Helper::intValueSupported($OldThisFileInfo['filesize'])) {
250  $this->errors[] = 'Unable to remove ID3v2 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
251  fclose($fp_source);
252 
253  return false;
254  }
255  rewind($fp_source);
256  if ($OldThisFileInfo['avdataoffset'] !== false) {
257  fseek($fp_source, $OldThisFileInfo['avdataoffset'], SEEK_SET);
258  }
259  if ($fp_temp = tmpfile()) {
260  while ($buffer = fread($fp_source, $this->fread_buffer_size)) {
261  fwrite($fp_temp, $buffer, strlen($buffer));
262  }
263  fclose($fp_source);
264  if (is_writable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'wb'))) {
265  rewind($fp_temp);
266  while ($buffer = fread($fp_temp, $this->fread_buffer_size)) {
267  fwrite($fp_source, $buffer, strlen($buffer));
268  }
269  fseek($fp_temp, -128, SEEK_END);
270  fclose($fp_source);
271  } else {
272  $this->errors[] = 'Could not fopen("'.$this->filename.'", "wb")';
273  }
274  fclose($fp_temp);
275  } else {
276  $this->errors[] = 'Could not create tmpfile()';
277  }
278  } else {
279  $this->errors[] = 'Could not fopen("'.$this->filename.'", "rb")';
280  }
281 
282  } else {
283 
284  $this->errors[] = 'Directory and file both not writeable';
285 
286  }
287 
288  if (!empty($this->errors)) {
289  return false;
290  }
291 
292  return true;
293  }
fseek($bytes, $whence=SEEK_SET)
static intValueSupported($num)
null $hasINT64
Definition: Helper.php:130
+ Here is the call graph for this function:

◆ safe_parse_url()

GetId3\Write\Id3v2::safe_parse_url (   $url)
Parameters
type$url
Returns
type

Definition at line 2086 of file Id3v2.php.

References $url.

Referenced by GetId3\Write\Id3v2\IsValidURL().

2087  {
2088  $parts = @parse_url($url);
2089  $parts['scheme'] = (isset($parts['scheme']) ? $parts['scheme'] : '');
2090  $parts['host'] = (isset($parts['host']) ? $parts['host'] : '');
2091  $parts['user'] = (isset($parts['user']) ? $parts['user'] : '');
2092  $parts['pass'] = (isset($parts['pass']) ? $parts['pass'] : '');
2093  $parts['path'] = (isset($parts['path']) ? $parts['path'] : '');
2094  $parts['query'] = (isset($parts['query']) ? $parts['query'] : '');
2095 
2096  return $parts;
2097  }
$url
Definition: shib_logout.php:72
+ Here is the caller graph for this function:

◆ Unsynchronise()

GetId3\Write\Id3v2::Unsynchronise (   $data)
Parameters
type$data
Returns
string

Definition at line 1959 of file Id3v2.php.

References $data.

Referenced by GetId3\Write\Id3v2\GenerateID3v2Tag().

1960  {
1961  // Whenever a false synchronisation is found within the tag, one zeroed
1962  // byte is inserted after the first false synchronisation byte. The
1963  // format of a correct sync that should be altered by ID3 encoders is as
1964  // follows:
1965  // %11111111 111xxxxx
1966  // And should be replaced with:
1967  // %11111111 00000000 111xxxxx
1968  // This has the side effect that all $FF 00 combinations have to be
1969  // altered, so they won't be affected by the decoding process. Therefore
1970  // all the $FF 00 combinations have to be replaced with the $FF 00 00
1971  // combination during the unsynchronisation.
1972 
1973  $data = str_replace("\xFF\x00", "\xFF\x00\x00", $data);
1974  $unsyncheddata = '';
1975  $datalength = strlen($data);
1976  for ($i = 0; $i < $datalength; $i++) {
1977  $thischar = $data{$i};
1978  $unsyncheddata .= $thischar;
1979  if ($thischar == "\xFF") {
1980  $nextchar = ord($data{$i + 1});
1981  if (($nextchar & 0xE0) == 0xE0) {
1982  // previous byte = 11111111, this byte = 111?????
1983  $unsyncheddata .= "\x00";
1984  }
1985  }
1986  }
1987 
1988  return $unsyncheddata;
1989  }
+ Here is the caller graph for this function:

◆ WriteID3v2()

GetId3\Write\Id3v2::WriteID3v2 ( )
Returns
boolean

Definition at line 94 of file Id3v2.php.

References GetId3\Write\Id3v2\array_join_merge(), GetId3\Handler\BaseHandler\fread(), GetId3\Handler\BaseHandler\fseek(), GetId3\Write\Id3v2\GenerateID3v2Tag(), GetId3\GetId3Core\getTempDir(), and GetId3\Lib\Helper\intValueSupported().

95  {
96  // File MUST be writeable - CHMOD(646) at least. It's best if the
97  // directory is also writeable, because that method is both faster and less susceptible to errors.
98 
99  if (!empty($this->filename) && (is_writeable($this->filename) || (!file_exists($this->filename) && is_writeable(dirname($this->filename))))) {
100  // Initialize GetId3 engine
101  $getID3 = new GetId3Core();
102  $OldThisFileInfo = $getID3->analyze($this->filename);
103  if (!Helper::intValueSupported($OldThisFileInfo['filesize'])) {
104  $this->errors[] = 'Unable to write ID3v2 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
105  fclose($fp_source);
106 
107  return false;
108  }
109  if ($this->merge_existing_data) {
110  // merge with existing data
111  if (!empty($OldThisFileInfo['id3v2'])) {
112  $this->tag_data = $this->array_join_merge($OldThisFileInfo['id3v2'], $this->tag_data);
113  }
114  }
115  $this->paddedlength = (isset($OldThisFileInfo['id3v2']['headerlength']) ? max($OldThisFileInfo['id3v2']['headerlength'], $this->paddedlength) : $this->paddedlength);
116 
117  if ($NewID3v2Tag = $this->GenerateID3v2Tag()) {
118 
119  if (file_exists($this->filename) && is_writeable($this->filename) && isset($OldThisFileInfo['id3v2']['headerlength']) && ($OldThisFileInfo['id3v2']['headerlength'] == strlen($NewID3v2Tag))) {
120 
121  // best and fastest method - insert-overwrite existing tag (padded to length of old tag if neccesary)
122  if (file_exists($this->filename)) {
123 
124  if (is_readable($this->filename) && is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'r+b'))) {
125  rewind($fp);
126  fwrite($fp, $NewID3v2Tag, strlen($NewID3v2Tag));
127  fclose($fp);
128  } else {
129  $this->errors[] = 'Could not fopen("'.$this->filename.'", "r+b")';
130  }
131 
132  } else {
133 
134  if (is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'wb'))) {
135  rewind($fp);
136  fwrite($fp, $NewID3v2Tag, strlen($NewID3v2Tag));
137  fclose($fp);
138  } else {
139  $this->errors[] = 'Could not fopen("'.$this->filename.'", "wb")';
140  }
141 
142  }
143 
144  } else {
145 
146  if ($tempfilename = tempnam(GetId3Core::getTempDir(), 'getID3')) {
147  if (is_readable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'rb'))) {
148  if (is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) {
149 
150  fwrite($fp_temp, $NewID3v2Tag, strlen($NewID3v2Tag));
151 
152  rewind($fp_source);
153  if (!empty($OldThisFileInfo['avdataoffset'])) {
154  fseek($fp_source, $OldThisFileInfo['avdataoffset'], SEEK_SET);
155  }
156 
157  while ($buffer = fread($fp_source, $this->fread_buffer_size)) {
158  fwrite($fp_temp, $buffer, strlen($buffer));
159  }
160 
161  fclose($fp_temp);
162  fclose($fp_source);
163  copy($tempfilename, $this->filename);
164  unlink($tempfilename);
165 
166  return true;
167 
168  } else {
169  $this->errors[] = 'Could not fopen("'.$tempfilename.'", "wb")';
170  }
171  fclose($fp_source);
172 
173  } else {
174  $this->errors[] = 'Could not fopen("'.$this->filename.'", "rb")';
175  }
176  }
177 
178  return false;
179 
180  }
181 
182  } else {
183 
184  $this->errors[] = '$this->GenerateID3v2Tag() failed';
185 
186  }
187 
188  if (!empty($this->errors)) {
189  return false;
190  }
191 
192  return true;
193  } else {
194  $this->errors[] = 'WriteID3v2() failed: !is_writeable('.$this->filename.')';
195  }
196 
197  return false;
198  }
GenerateID3v2Tag($noerrorsonly=true)
Definition: Id3v2.php:1636
fseek($bytes, $whence=SEEK_SET)
array_join_merge($arr1, $arr2)
Definition: Id3v2.php:2019
static intValueSupported($num)
null $hasINT64
Definition: Helper.php:130
+ Here is the call graph for this function:

Field Documentation

◆ $errors

GetId3\Write\Id3v2::$errors = array()

Definition at line 79 of file Id3v2.php.

◆ $filename

GetId3\Write\Id3v2::$filename

Definition at line 33 of file Id3v2.php.

◆ $fread_buffer_size

GetId3\Write\Id3v2::$fread_buffer_size = 32768

Definition at line 39 of file Id3v2.php.

◆ $id3v2_default_encodingid

GetId3\Write\Id3v2::$id3v2_default_encodingid = 0

Definition at line 64 of file Id3v2.php.

◆ $id3v2_use_unsynchronisation

GetId3\Write\Id3v2::$id3v2_use_unsynchronisation = false

Definition at line 69 of file Id3v2.php.

◆ $majorversion

GetId3\Write\Id3v2::$majorversion = 3

Definition at line 49 of file Id3v2.php.

Referenced by GetId3\Write\Id3v2\ID3v2ShortFrameNameLookup().

◆ $merge_existing_data

GetId3\Write\Id3v2::$merge_existing_data = false

Definition at line 59 of file Id3v2.php.

◆ $minorversion

GetId3\Write\Id3v2::$minorversion = 0

Definition at line 54 of file Id3v2.php.

◆ $paddedlength

GetId3\Write\Id3v2::$paddedlength = 4096

Definition at line 44 of file Id3v2.php.

◆ $tag_data

GetId3\Write\Id3v2::$tag_data

Definition at line 34 of file Id3v2.php.

◆ $warnings

GetId3\Write\Id3v2::$warnings = array()

Definition at line 74 of file Id3v2.php.


The documentation for this class was generated from the following file: