File Coverage

src/common.c
Criterion Covered Total %
statement 108 132 81.8
branch 38 62 61.2
condition n/a
subroutine n/a
pod n/a
total 146 194 75.2


line stmt bran cond sub pod time code
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 7058           _check_buf(PerlIO *infile, Buffer *buf, int min_wanted, int max_wanted)
22             {
23 7058           int ret = 1;
24              
25             // Do we have enough data?
26 7058 100         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 1171 100         if (min_wanted > max_wanted) {
37 22           max_wanted = min_wanted;
38             }
39              
40             // Adjust actual amount to read by the amount we already have in the buffer
41 1171           actual_wanted = max_wanted - buffer_len(buf);
42              
43 1171           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 1171 100         if ( (read = PerlIO_read(infile, tmp, actual_wanted)) <= 0 ) {
50 1 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 0           warn("Error reading: %s (wanted %d)\n", strerror(errno), actual_wanted);
60             #endif
61             }
62             else {
63 1           warn("Error: Unable to read at least %d bytes from file.\n", min_wanted);
64             }
65              
66 1           ret = 0;
67 1           goto out;
68             }
69              
70 1170           buffer_append(buf, tmp, read);
71              
72             // Make sure we got enough
73 1170 50         if ( buffer_len(buf) < min_wanted ) {
74 0           warn("Error: Unable to read at least %d bytes from file (only read %d).\n", min_wanted, read);
75 0           ret = 0;
76 0           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 1171           Safefree(tmp);
91             }
92              
93 7058           return ret;
94             }
95              
96 1091           char* upcase(char *s) {
97 1091           char *p = &s[0];
98              
99 10862 100         while (*p != 0) {
100 9771 100         *p = toUPPER(*p);
101 9771           p++;
102             }
103              
104 1091           return s;
105             }
106              
107 256           void _split_vorbis_comment(char* comment, HV* tags) {
108             char *half;
109             char *key;
110 256           int klen = 0;
111 256           SV* value = NULL;
112              
113 256 50         if (!comment) {
114             DEBUG_TRACE("Empty comment, skipping...\n");
115 0           return;
116             }
117              
118             /* store the pointer location of the '=', poor man's split() */
119 256           half = strchr(comment, '=');
120              
121 256 50         if (half == NULL) {
122             DEBUG_TRACE("Comment \"%s\" missing \'=\', skipping...\n", comment);
123 0           return;
124             }
125              
126 256           klen = half - comment;
127 256           value = newSVpv(half + 1, 0);
128 256           sv_utf8_decode(value);
129              
130             /* Is there a better way to do this? */
131 256           New(0, key, klen + 1, char);
132 256           Move(comment, key, klen, char);
133 256           key[klen] = '\0';
134 256           key = upcase(key);
135              
136 256 100         if (hv_exists(tags, key, klen)) {
137             /* fetch the existing key */
138 2           SV **entry = my_hv_fetch(tags, key);
139              
140 2 50         if (SvOK(*entry)) {
    0          
    0          
141              
142             // A normal string entry, convert to array.
143 2 100         if (SvTYPE(*entry) == SVt_PV) {
144 1           AV *ref = newAV();
145 1           av_push(ref, newSVsv(*entry));
146 1           av_push(ref, value);
147 1           my_hv_store(tags, key, newRV_noinc((SV*)ref));
148              
149 1 50         } else if (SvTYPE(SvRV(*entry)) == SVt_PVAV) {
150 2           av_push((AV *)SvRV(*entry), value);
151             }
152             }
153              
154             } else {
155 254           my_hv_store(tags, key, value);
156             }
157              
158 256           Safefree(key);
159             }
160              
161             int32_t
162 6           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 6 50         if (PerlIO_seek(infile, 0, SEEK_SET) < 0)
169 0           return 0;
170              
171 6           PerlIO_read(infile, &buf, sizeof(buf));
172              
173             // check id3-tag
174 6 50         if (memcmp(buf, "ID3", 3) != 0)
175 6           return 0;
176              
177             // read flags
178 0           has_footer = buf[5] & 0x10;
179              
180 0 0         if (buf[5] & 0x0F)
181 0           return -1;
182              
183 0 0         if ((buf[6] | buf[7] | buf[8] | buf[9]) & 0x80)
184 0           return -1;
185              
186             // read header size (syncsave: 4 * $0xxxxxxx = 28 significant bits)
187 0           size = buf[6] << 21;
188 0           size += buf[7] << 14;
189 0           size += buf[8] << 7;
190 0           size += buf[9] ;
191 0           size += 10;
192              
193 0 0         if (has_footer)
194 0           size += 10;
195              
196 6           return size;
197             }
198              
199             uint32_t
200 47           _bitrate(uint32_t audio_size, uint32_t song_length_ms)
201             {
202 47           return ( (audio_size * 1.0) / song_length_ms ) * 8000;
203             }
204              
205             off_t
206 302           _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 302 50         if ( !fstat( PerlIO_fileno(infile), &buf ) ) {
221 302           return buf.st_size;
222             }
223              
224 0           warn("Unable to stat: %s\n", strerror(errno));
225              
226 302           return 0;
227             #endif
228             }
229              
230             int
231 66           _env_true(const char *name)
232             {
233             char *value;
234              
235 66           value = getenv(name);
236              
237 66 100         if ( value == NULL || value[0] == '0' ) {
    100          
238 51           return 0;
239             }
240              
241 15           return 1;
242             }
243              
244             // from http://jeremie.com/frolic/base64/
245             int
246 7           _decode_base64(char *s)
247             {
248 7           char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
249             int bit_offset, byte_offset, idx, i, n;
250 7           unsigned char *d = (unsigned char *)s;
251             char *p;
252              
253 7           n = i = 0;
254              
255 317615 50         while (*s && (p=strchr(b64,*s))) {
    100          
256 317608           idx = (int)(p - b64);
257 317608           byte_offset = (i*6)/8;
258 317608           bit_offset = (i*6)%8;
259 317608           d[byte_offset] &= ~((1<<(8-bit_offset))-1);
260              
261 317608 100         if (bit_offset < 3) {
262 158804           d[byte_offset] |= (idx << (2-bit_offset));
263 158804           n = byte_offset+1;
264             }
265             else {
266 158804           d[byte_offset] |= (idx >> (bit_offset-2));
267 158804           d[byte_offset+1] = 0;
268 158804           d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
269 158804           n = byte_offset+2;
270             }
271 317608           s++;
272 317608           i++;
273             }
274              
275             /* null terminate */
276 7           d[n] = 0;
277              
278 7           return n;
279             }
280              
281             HV *
282 6           _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 6           HV *picture = newHV();
288              
289             // Check we have enough for picture_type and mime_length
290 6 50         if ( !_check_buf(infile, buf, 8, DEFAULT_BLOCK_SIZE) ) {
291 0           return NULL;
292             }
293              
294 6           my_hv_store( picture, "picture_type", newSVuv( buffer_get_int(buf) ) );
295              
296 6           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 6 50         if ( !_check_buf(infile, buf, mime_length + 4, DEFAULT_BLOCK_SIZE) ) {
301 0           return NULL;
302             }
303              
304 6           my_hv_store( picture, "mime_type", newSVpvn( buffer_ptr(buf), mime_length ) );
305 6           buffer_consume(buf, mime_length);
306              
307 6           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 6 50         if ( !_check_buf(infile, buf, desc_length + 20, DEFAULT_BLOCK_SIZE) ) {
312 0           return NULL;
313             }
314              
315 6           desc = newSVpvn( buffer_ptr(buf), desc_length );
316 6           sv_utf8_decode(desc); // XXX needs test with utf8 desc
317 6           my_hv_store( picture, "description", desc );
318 6           buffer_consume(buf, desc_length);
319              
320 6           my_hv_store( picture, "width", newSVuv( buffer_get_int(buf) ) );
321 6           my_hv_store( picture, "height", newSVuv( buffer_get_int(buf) ) );
322 6           my_hv_store( picture, "depth", newSVuv( buffer_get_int(buf) ) );
323 6           my_hv_store( picture, "color_index", newSVuv( buffer_get_int(buf) ) );
324              
325 6           *pic_length = buffer_get_int(buf);
326             DEBUG_TRACE(" pic_length: %d\n", *pic_length);
327              
328 6 100         if ( _env_true("AUDIO_SCAN_NO_ARTWORK") ) {
329 3           my_hv_store( picture, "image_data", newSVuv(*pic_length) );
330             }
331             else {
332 3 50         if ( !_check_buf(infile, buf, *pic_length, *pic_length) ) {
333 0           return NULL;
334             }
335              
336 3           my_hv_store( picture, "image_data", newSVpvn( buffer_ptr(buf), *pic_length ) );
337             }
338              
339 6           return picture;
340             }