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