1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16 
17 #include "common.h"
18 #include "buffer.c"
19 
20 int
21 _check_buf(PerlIO *infile, Buffer *buf, int min_wanted, int max_wanted)
22 {
23   int ret = 1;
24 
25   // Do we have enough data?
26   if ( buffer_len(buf) < min_wanted ) {
27     // Read more data
28     uint32_t read;
29     uint32_t actual_wanted;
30     unsigned char *tmp;
31 
32 #ifdef _MSC_VER
33     uint32_t pos_check = PerlIO_tell(infile);
34 #endif
35 
36     if (min_wanted > max_wanted) {
37       max_wanted = min_wanted;
38     }
39 
40     // Adjust actual amount to read by the amount we already have in the buffer
41     actual_wanted = max_wanted - buffer_len(buf);
42 
43     New(0, tmp, actual_wanted, unsigned char);
44 
45     DEBUG_TRACE("Buffering from file @ %d (min_wanted %d, max_wanted %d, adjusted to %d)\n",
46       (int)PerlIO_tell(infile), min_wanted, max_wanted, actual_wanted
47     );
48 
49     if ( (read = PerlIO_read(infile, tmp, actual_wanted)) <= 0 ) {
50       if ( PerlIO_error(infile) ) {
51 #ifdef _MSC_VER
52         // Show windows specific error message as Win32 PerlIO_read does not set errno
53         DWORD last_error = GetLastError();
54         LPWSTR *errmsg = NULL;
55         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, last_error, 0, (LPWSTR)&errmsg, 0, NULL);
56         warn("Error reading: %d %s (read %d wanted %d)\n", last_error, errmsg, read, actual_wanted);
57         LocalFree(errmsg);
58 #else
59         warn("Error reading: %s (wanted %d)\n", strerror(errno), actual_wanted);
60 #endif
61       }
62       else {
63         warn("Error: Unable to read at least %d bytes from file.\n", min_wanted);
64       }
65 
66       ret = 0;
67       goto out;
68     }
69 
70     buffer_append(buf, tmp, read);
71 
72     // Make sure we got enough
73     if ( buffer_len(buf) < min_wanted ) {
74       warn("Error: Unable to read at least %d bytes from file (only read %d).\n", min_wanted, read);
75       ret = 0;
76       goto out;
77     }
78 
79 #ifdef _MSC_VER
80     // Bug 16095, weird off-by-one bug seen only on Win32 and only when reading a filehandle
81     if (PerlIO_tell(infile) != pos_check + read) {
82       //PerlIO_printf(PerlIO_stderr(), "Win32 bug, pos should be %d, but was %d\n", pos_check + read, PerlIO_tell(infile));
83       PerlIO_seek(infile, pos_check + read, SEEK_SET);
84     }
85 #endif
86 
87     DEBUG_TRACE("Buffered %d bytes, new pos %d\n", read, (int)PerlIO_tell(infile));
88 
89 out:
90     Safefree(tmp);
91   }
92 
93   return ret;
94 }
95 
96 char* upcase(char *s) {
97   char *p = &s[0];
98 
99   while (*p != 0) {
100     *p = toUPPER(*p);
101     p++;
102   }
103 
104   return s;
105 }
106 
107 void _split_vorbis_comment(char* comment, HV* tags) {
108   char *half;
109   char *key;
110   int klen  = 0;
111   SV* value = NULL;
112 
113   if (!comment) {
114     DEBUG_TRACE("Empty comment, skipping...\n");
115     return;
116   }
117 
118   /* store the pointer location of the '=', poor man's split() */
119   half = strchr(comment, '=');
120 
121   if (half == NULL) {
122     DEBUG_TRACE("Comment \"%s\" missing \'=\', skipping...\n", comment);
123     return;
124   }
125 
126   klen  = half - comment;
127   value = newSVpv(half + 1, 0);
128   sv_utf8_decode(value);
129 
130   /* Is there a better way to do this? */
131   New(0, key, klen + 1, char);
132   Move(comment, key, klen, char);
133   key[klen] = '\0';
134   key = upcase(key);
135 
136   if (hv_exists(tags, key, klen)) {
137     /* fetch the existing key */
138     SV **entry = my_hv_fetch(tags, key);
139 
140     if (SvOK(*entry)) {
141 
142       // A normal string entry, convert to array.
143       if (SvTYPE(*entry) == SVt_PV) {
144         AV *ref = newAV();
145         av_push(ref, newSVsv(*entry));
146         av_push(ref, value);
147         my_hv_store(tags, key, newRV_noinc((SV*)ref));
148 
149       } else if (SvTYPE(SvRV(*entry)) == SVt_PVAV) {
150         av_push((AV *)SvRV(*entry), value);
151       }
152     }
153 
154   } else {
155     my_hv_store(tags, key, value);
156   }
157 
158   Safefree(key);
159 }
160 
161 int32_t
162 skip_id3v2(PerlIO* infile) {
163   unsigned char buf[10];
164   uint32_t has_footer;
165   int32_t  size;
166 
167   // seek to first byte of mpc data
168   if (PerlIO_seek(infile, 0, SEEK_SET) < 0)
169     return 0;
170 
171   PerlIO_read(infile, &buf, sizeof(buf));
172 
173   // check id3-tag
174   if (memcmp(buf, "ID3", 3) != 0)
175     return 0;
176 
177   // read flags
178   has_footer = buf[5] & 0x10;
179 
180   if (buf[5] & 0x0F)
181     return -1;
182 
183   if ((buf[6] | buf[7] | buf[8] | buf[9]) & 0x80)
184     return -1;
185 
186   // read header size (syncsave: 4 * $0xxxxxxx = 28 significant bits)
187   size  = buf[6] << 21;
188   size += buf[7] << 14;
189   size += buf[8] <<  7;
190   size += buf[9]      ;
191   size += 10;
192 
193   if (has_footer)
194     size += 10;
195 
196   return size;
197 }
198 
199 uint32_t
200 _bitrate(uint32_t audio_size, uint32_t song_length_ms)
201 {
202   return ( (audio_size * 1.0) / song_length_ms ) * 8000;
203 }
204 
205 off_t
206 _file_size(PerlIO *infile)
207 {
208 #ifdef _MSC_VER
209   // Win32 doesn't work right with fstat
210   off_t file_size;
211 
212   PerlIO_seek(infile, 0, SEEK_END);
213   file_size = PerlIO_tell(infile);
214   PerlIO_seek(infile, 0, SEEK_SET);
215 
216   return file_size;
217 #else
218   struct stat buf;
219 
220   if ( !fstat( PerlIO_fileno(infile), &buf ) ) {
221     return buf.st_size;
222   }
223 
224   warn("Unable to stat: %s\n", strerror(errno));
225 
226   return 0;
227 #endif
228 }
229 
230 int
231 _env_true(const char *name)
232 {
233   char *value;
234 
235   value = getenv(name);
236 
237   if ( value == NULL || value[0] == '0' ) {
238     return 0;
239   }
240 
241   return 1;
242 }
243 
244 // from http://jeremie.com/frolic/base64/
245 int
246 _decode_base64(char *s)
247 {
248   char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
249   int bit_offset, byte_offset, idx, i, n;
250   unsigned char *d = (unsigned char *)s;
251   char *p;
252 
253   n = i = 0;
254 
255   while (*s && (p=strchr(b64,*s))) {
256     idx = (int)(p - b64);
257     byte_offset = (i*6)/8;
258     bit_offset = (i*6)%8;
259     d[byte_offset] &= ~((1<<(8-bit_offset))-1);
260 
261     if (bit_offset < 3) {
262       d[byte_offset] |= (idx << (2-bit_offset));
263       n = byte_offset+1;
264     }
265     else {
266       d[byte_offset] |= (idx >> (bit_offset-2));
267       d[byte_offset+1] = 0;
268       d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
269       n = byte_offset+2;
270     }
271     s++;
272     i++;
273   }
274 
275   /* null terminate */
276   d[n] = 0;
277 
278   return n;
279 }
280 
281 HV *
282 _decode_flac_picture(PerlIO *infile, Buffer *buf, uint32_t *pic_length)
283 {
284   uint32_t mime_length;
285   uint32_t desc_length;
286   SV *desc;
287   HV *picture = newHV();
288 
289   // Check we have enough for picture_type and mime_length
290   if ( !_check_buf(infile, buf, 8, DEFAULT_BLOCK_SIZE) ) {
291     return NULL;
292   }
293 
294   my_hv_store( picture, "picture_type", newSVuv( buffer_get_int(buf) ) );
295 
296   mime_length = buffer_get_int(buf);
297   DEBUG_TRACE("  mime_length: %d\n", mime_length);
298 
299   // Check we have enough for mime_type and desc_length
300   if ( !_check_buf(infile, buf, mime_length + 4, DEFAULT_BLOCK_SIZE) ) {
301     return NULL;
302   }
303 
304   my_hv_store( picture, "mime_type", newSVpvn( buffer_ptr(buf), mime_length ) );
305   buffer_consume(buf, mime_length);
306 
307   desc_length = buffer_get_int(buf);
308   DEBUG_TRACE("  desc_length: %d\n", mime_length);
309 
310   // Check we have enough for desc_length, width, height, depth, color_index, pic_length
311   if ( !_check_buf(infile, buf, desc_length + 20, DEFAULT_BLOCK_SIZE) ) {
312     return NULL;
313   }
314 
315   desc = newSVpvn( buffer_ptr(buf), desc_length );
316   sv_utf8_decode(desc); // XXX needs test with utf8 desc
317   my_hv_store( picture, "description", desc );
318   buffer_consume(buf, desc_length);
319 
320   my_hv_store( picture, "width", newSVuv( buffer_get_int(buf) ) );
321   my_hv_store( picture, "height", newSVuv( buffer_get_int(buf) ) );
322   my_hv_store( picture, "depth", newSVuv( buffer_get_int(buf) ) );
323   my_hv_store( picture, "color_index", newSVuv( buffer_get_int(buf) ) );
324 
325   *pic_length = buffer_get_int(buf);
326   DEBUG_TRACE("  pic_length: %d\n", *pic_length);
327 
328   if ( _env_true("AUDIO_SCAN_NO_ARTWORK") ) {
329     my_hv_store( picture, "image_data", newSVuv(*pic_length) );
330   }
331   else {
332     if ( !_check_buf(infile, buf, *pic_length, *pic_length) ) {
333       return NULL;
334     }
335 
336     my_hv_store( picture, "image_data", newSVpvn( buffer_ptr(buf), *pic_length ) );
337   }
338 
339   return picture;
340 }
341