source: branches/MootoolsFileManager-Update/plugins/MootoolsFileManager/mootools-filemanager/Assets/Connector/Assets/getid3/write.apetag.php @ 1300

Last change on this file since 1300 was 1300, checked in by gogo, 8 years ago

Update the MootoolsFileManager? to the latest cpojer with some modifications.
Add a demo for the MFM examples/mootools-file-manager.php
Change the default config for ImageManager? and ExtendedFileManager? for added security.

File size: 7.4 KB
Line 
1<?php
2/////////////////////////////////////////////////////////////////
3/// getID3() by James Heinrich <info@getid3.org>               //
4//  available at http://getid3.sourceforge.net                 //
5//            or http://www.getid3.org                         //
6/////////////////////////////////////////////////////////////////
7// See readme.txt for more details                             //
8/////////////////////////////////////////////////////////////////
9//                                                             //
10// write.apetag.php                                            //
11// module for writing APE tags                                 //
12// dependencies: module.tag.apetag.php                         //
13//                                                            ///
14/////////////////////////////////////////////////////////////////
15
16
17getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.apetag.php', __FILE__, true);
18
19class getid3_write_apetag
20{
21
22        var $filename;
23        var $tag_data;
24        var $always_preserve_replaygain = true;  // ReplayGain / MP3gain tags will be copied from old tag even if not passed in data
25        var $warnings = array();                 // any non-critical errors will be stored here
26        var $errors   = array();                 // any critical errors will be stored here
27
28        function getid3_write_apetag() {
29                return true;
30        }
31
32        function WriteAPEtag() {
33                // NOTE: All data passed to this function must be UTF-8 format
34
35                $getID3 = new getID3;
36                $ThisFileInfo = $getID3->analyze($this->filename);
37
38                if (isset($ThisFileInfo['ape']['tag_offset_start']) && isset($ThisFileInfo['lyrics3']['tag_offset_end'])) {
39                        if ($ThisFileInfo['ape']['tag_offset_start'] >= $ThisFileInfo['lyrics3']['tag_offset_end']) {
40                                // Current APE tag between Lyrics3 and ID3v1/EOF
41                                // This break Lyrics3 functionality
42                                if (!$this->DeleteAPEtag()) {
43                                        return false;
44                                }
45                                $ThisFileInfo = $getID3->analyze($this->filename);
46                        }
47                }
48
49                if ($this->always_preserve_replaygain) {
50                        $ReplayGainTagsToPreserve = array('mp3gain_minmax', 'mp3gain_album_minmax', 'mp3gain_undo', 'replaygain_track_peak', 'replaygain_track_gain', 'replaygain_album_peak', 'replaygain_album_gain');
51                        foreach ($ReplayGainTagsToPreserve as $rg_key) {
52                                if (isset($ThisFileInfo['ape']['items'][strtolower($rg_key)]['data'][0]) && !isset($this->tag_data[strtoupper($rg_key)][0])) {
53                                        $this->tag_data[strtoupper($rg_key)][0] = $ThisFileInfo['ape']['items'][strtolower($rg_key)]['data'][0];
54                                }
55                        }
56                }
57
58                if ($APEtag = $this->GenerateAPEtag()) {
59                        ob_start();
60                        if ($fp = fopen($this->filename, 'a+b')) {
61                                ob_end_clean();
62                                $oldignoreuserabort = ignore_user_abort(true);
63                                flock($fp, LOCK_EX);
64
65                                $PostAPEdataOffset = $ThisFileInfo['avdataend'];
66                                if (isset($ThisFileInfo['ape']['tag_offset_end'])) {
67                                        $PostAPEdataOffset = max($PostAPEdataOffset, $ThisFileInfo['ape']['tag_offset_end']);
68                                }
69                                if (isset($ThisFileInfo['lyrics3']['tag_offset_start'])) {
70                                        $PostAPEdataOffset = max($PostAPEdataOffset, $ThisFileInfo['lyrics3']['tag_offset_start']);
71                                }
72                                fseek($fp, $PostAPEdataOffset, SEEK_SET);
73                                $PostAPEdata = '';
74                                if ($ThisFileInfo['filesize'] > $PostAPEdataOffset) {
75                                        $PostAPEdata = fread($fp, $ThisFileInfo['filesize'] - $PostAPEdataOffset);
76                                }
77
78                                fseek($fp, $PostAPEdataOffset, SEEK_SET);
79                                if (isset($ThisFileInfo['ape']['tag_offset_start'])) {
80                                        fseek($fp, $ThisFileInfo['ape']['tag_offset_start'], SEEK_SET);
81                                }
82                                ftruncate($fp, ftell($fp));
83                                fwrite($fp, $APEtag, strlen($APEtag));
84                                if (!empty($PostAPEdata)) {
85                                        fwrite($fp, $PostAPEdata, strlen($PostAPEdata));
86                                }
87                                flock($fp, LOCK_UN);
88                                fclose($fp);
89                                ignore_user_abort($oldignoreuserabort);
90                                return true;
91                        }
92                        $errormessage = ob_get_contents();
93                        ob_end_clean();
94                        return false;
95                }
96                return false;
97        }
98
99        function DeleteAPEtag() {
100                $getID3 = new getID3;
101                $ThisFileInfo = $getID3->analyze($this->filename);
102                if (isset($ThisFileInfo['ape']['tag_offset_start']) && isset($ThisFileInfo['ape']['tag_offset_end'])) {
103                        ob_start();
104                        if ($fp = fopen($this->filename, 'a+b')) {
105                                ob_end_clean();
106
107                                flock($fp, LOCK_EX);
108                                $oldignoreuserabort = ignore_user_abort(true);
109
110                                fseek($fp, $ThisFileInfo['ape']['tag_offset_end'], SEEK_SET);
111                                $DataAfterAPE = '';
112                                if ($ThisFileInfo['filesize'] > $ThisFileInfo['ape']['tag_offset_end']) {
113                                        $DataAfterAPE = fread($fp, $ThisFileInfo['filesize'] - $ThisFileInfo['ape']['tag_offset_end']);
114                                }
115
116                                ftruncate($fp, $ThisFileInfo['ape']['tag_offset_start']);
117                                fseek($fp, $ThisFileInfo['ape']['tag_offset_start'], SEEK_SET);
118
119                                if (!empty($DataAfterAPE)) {
120                                        fwrite($fp, $DataAfterAPE, strlen($DataAfterAPE));
121                                }
122
123                                flock($fp, LOCK_UN);
124                                fclose($fp);
125                                ignore_user_abort($oldignoreuserabort);
126
127                                return true;
128                        }
129                        $errormessage = ob_get_contents();
130                        ob_end_clean();
131                        return false;
132                }
133                return true;
134        }
135
136
137        function GenerateAPEtag() {
138                // NOTE: All data passed to this function must be UTF-8 format
139
140                $items = array();
141                if (!is_array($this->tag_data)) {
142                        return false;
143                }
144                foreach ($this->tag_data as $key => $arrayofvalues) {
145                        if (!is_array($arrayofvalues)) {
146                                return false;
147                        }
148
149                        $valuestring = '';
150                        foreach ($arrayofvalues as $value) {
151                                $valuestring .= str_replace("\x00", '', $value)."\x00";
152                        }
153                        $valuestring = rtrim($valuestring, "\x00");
154
155                        // Length of the assigned value in bytes
156                        $tagitem  = getid3_lib::LittleEndian2String(strlen($valuestring), 4);
157
158                        //$tagitem .= $this->GenerateAPEtagFlags(true, true, false, 0, false);
159                        $tagitem .= "\x00\x00\x00\x00";
160
161                        $tagitem .= $this->CleanAPEtagItemKey($key)."\x00";
162                        $tagitem .= $valuestring;
163
164                        $items[] = $tagitem;
165
166                }
167
168                return $this->GenerateAPEtagHeaderFooter($items, true).implode('', $items).$this->GenerateAPEtagHeaderFooter($items, false);
169        }
170
171        function GenerateAPEtagHeaderFooter(&$items, $isheader=false) {
172                $tagdatalength = 0;
173                foreach ($items as $itemdata) {
174                        $tagdatalength += strlen($itemdata);
175                }
176
177                $APEheader  = 'APETAGEX';
178                $APEheader .= getid3_lib::LittleEndian2String(2000, 4);
179                $APEheader .= getid3_lib::LittleEndian2String(32 + $tagdatalength, 4);
180                $APEheader .= getid3_lib::LittleEndian2String(count($items), 4);
181                $APEheader .= $this->GenerateAPEtagFlags(true, true, $isheader, 0, false);
182                $APEheader .= str_repeat("\x00", 8);
183
184                return $APEheader;
185        }
186
187        function GenerateAPEtagFlags($header=true, $footer=true, $isheader=false, $encodingid=0, $readonly=false) {
188                $APEtagFlags = array_fill(0, 4, 0);
189                if ($header) {
190                        $APEtagFlags[0] |= 0x80; // Tag contains a header
191                }
192                if (!$footer) {
193                        $APEtagFlags[0] |= 0x40; // Tag contains no footer
194                }
195                if ($isheader) {
196                        $APEtagFlags[0] |= 0x20; // This is the header, not the footer
197                }
198
199                // 0: Item contains text information coded in UTF-8
200                // 1: Item contains binary information °)
201                // 2: Item is a locator of external stored information °°)
202                // 3: reserved
203                $APEtagFlags[3] |= ($encodingid << 1);
204
205                if ($readonly) {
206                        $APEtagFlags[3] |= 0x01; // Tag or Item is Read Only
207                }
208
209                return chr($APEtagFlags[3]).chr($APEtagFlags[2]).chr($APEtagFlags[1]).chr($APEtagFlags[0]);
210        }
211
212        function CleanAPEtagItemKey($itemkey) {
213                $itemkey = preg_replace("#[^\x20-\x7E]#i", '', $itemkey);
214
215                // http://www.personal.uni-jena.de/~pfk/mpp/sv8/apekey.html
216                switch (strtoupper($itemkey)) {
217                        case 'EAN/UPC':
218                        case 'ISBN':
219                        case 'LC':
220                        case 'ISRC':
221                                $itemkey = strtoupper($itemkey);
222                                break;
223
224                        default:
225                                $itemkey = ucwords($itemkey);
226                                break;
227                }
228                return $itemkey;
229
230        }
231
232}
233
234?>
Note: See TracBrowser for help on using the repository browser.