20 |
20 |
21 public function Analyze() { |
21 public function Analyze() { |
22 $info = &$this->getid3->info; |
22 $info = &$this->getid3->info; |
23 |
23 |
24 if (!getid3_lib::intValueSupported($info['filesize'])) { |
24 if (!getid3_lib::intValueSupported($info['filesize'])) { |
25 $info['warning'][] = 'Unable to check for ID3v1 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB'; |
25 $this->warning('Unable to check for ID3v1 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB'); |
26 return false; |
26 return false; |
27 } |
27 } |
28 |
28 |
29 $this->fseek(-256, SEEK_END); |
29 $this->fseek(-256, SEEK_END); |
30 $preid3v1 = $this->fread(128); |
30 $preid3v1 = $this->fread(128); |
58 } |
58 } |
59 |
59 |
60 foreach ($ParsedID3v1 as $key => $value) { |
60 foreach ($ParsedID3v1 as $key => $value) { |
61 $ParsedID3v1['comments'][$key][0] = $value; |
61 $ParsedID3v1['comments'][$key][0] = $value; |
62 } |
62 } |
|
63 // ID3v1 encoding detection hack START |
|
64 // ID3v1 is defined as always using ISO-8859-1 encoding, but it is not uncommon to find files tagged with ID3v1 using Windows-1251 or other character sets |
|
65 // Since ID3v1 has no concept of character sets there is no certain way to know we have the correct non-ISO-8859-1 character set, but we can guess |
|
66 $ID3v1encoding = 'ISO-8859-1'; |
|
67 foreach ($ParsedID3v1['comments'] as $tag_key => $valuearray) { |
|
68 foreach ($valuearray as $key => $value) { |
|
69 if (preg_match('#^[\\x00-\\x40\\xA8\\B8\\x80-\\xFF]+$#', $value)) { |
|
70 foreach (array('Windows-1251', 'KOI8-R') as $id3v1_bad_encoding) { |
|
71 if (function_exists('mb_convert_encoding') && @mb_convert_encoding($value, $id3v1_bad_encoding, $id3v1_bad_encoding) === $value) { |
|
72 $ID3v1encoding = $id3v1_bad_encoding; |
|
73 break 3; |
|
74 } elseif (function_exists('iconv') && @iconv($id3v1_bad_encoding, $id3v1_bad_encoding, $value) === $value) { |
|
75 $ID3v1encoding = $id3v1_bad_encoding; |
|
76 break 3; |
|
77 } |
|
78 } |
|
79 } |
|
80 } |
|
81 } |
|
82 // ID3v1 encoding detection hack END |
63 |
83 |
64 // ID3v1 data is supposed to be padded with NULL characters, but some taggers pad with spaces |
84 // ID3v1 data is supposed to be padded with NULL characters, but some taggers pad with spaces |
65 $GoodFormatID3v1tag = $this->GenerateID3v1Tag( |
85 $GoodFormatID3v1tag = $this->GenerateID3v1Tag( |
66 $ParsedID3v1['title'], |
86 $ParsedID3v1['title'], |
67 $ParsedID3v1['artist'], |
87 $ParsedID3v1['artist'], |
71 $ParsedID3v1['comment'], |
91 $ParsedID3v1['comment'], |
72 (!empty($ParsedID3v1['track']) ? $ParsedID3v1['track'] : '')); |
92 (!empty($ParsedID3v1['track']) ? $ParsedID3v1['track'] : '')); |
73 $ParsedID3v1['padding_valid'] = true; |
93 $ParsedID3v1['padding_valid'] = true; |
74 if ($id3v1tag !== $GoodFormatID3v1tag) { |
94 if ($id3v1tag !== $GoodFormatID3v1tag) { |
75 $ParsedID3v1['padding_valid'] = false; |
95 $ParsedID3v1['padding_valid'] = false; |
76 $info['warning'][] = 'Some ID3v1 fields do not use NULL characters for padding'; |
96 $this->warning('Some ID3v1 fields do not use NULL characters for padding'); |
77 } |
97 } |
78 |
98 |
79 $ParsedID3v1['tag_offset_end'] = $info['filesize']; |
99 $ParsedID3v1['tag_offset_end'] = $info['filesize']; |
80 $ParsedID3v1['tag_offset_start'] = $ParsedID3v1['tag_offset_end'] - 128; |
100 $ParsedID3v1['tag_offset_start'] = $ParsedID3v1['tag_offset_end'] - 128; |
81 |
101 |
82 $info['id3v1'] = $ParsedID3v1; |
102 $info['id3v1'] = $ParsedID3v1; |
|
103 $info['id3v1']['encoding'] = $ID3v1encoding; |
83 } |
104 } |
84 |
105 |
85 if (substr($preid3v1, 0, 3) == 'TAG') { |
106 if (substr($preid3v1, 0, 3) == 'TAG') { |
86 // The way iTunes handles tags is, well, brain-damaged. |
107 // The way iTunes handles tags is, well, brain-damaged. |
87 // It completely ignores v1 if ID3v2 is present. |
108 // It completely ignores v1 if ID3v2 is present. |
93 // an APE tag footer was found before the last ID3v1, assume false "TAG" synch |
114 // an APE tag footer was found before the last ID3v1, assume false "TAG" synch |
94 } elseif (substr($preid3v1, 119, 6) == 'LYRICS') { |
115 } elseif (substr($preid3v1, 119, 6) == 'LYRICS') { |
95 // a Lyrics3 tag footer was found before the last ID3v1, assume false "TAG" synch |
116 // a Lyrics3 tag footer was found before the last ID3v1, assume false "TAG" synch |
96 } else { |
117 } else { |
97 // APE and Lyrics3 footers not found - assume double ID3v1 |
118 // APE and Lyrics3 footers not found - assume double ID3v1 |
98 $info['warning'][] = 'Duplicate ID3v1 tag detected - this has been known to happen with iTunes'; |
119 $this->warning('Duplicate ID3v1 tag detected - this has been known to happen with iTunes'); |
99 $info['avdataend'] -= 128; |
120 $info['avdataend'] -= 128; |
100 } |
121 } |
101 } |
122 } |
102 |
123 |
103 return true; |
124 return true; |