Skip to content

Commit d47182a

Browse files
author
wordofglass
committed
fetchart: do not rely on the server-provided Content-Type, but determine the image format from the file magic
1 parent cc6465d commit d47182a

File tree

1 file changed

+30
-11
lines changed

1 file changed

+30
-11
lines changed

beetsplug/fetchart.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from beets import ui
3030
from beets import util
3131
from beets import config
32+
from beets.mediafile import _image_mime_type
3233
from beets.util.artresizer import ArtResizer
3334
from beets.util import confit
3435
from beets.util import syspath, bytestring_path
@@ -231,21 +232,39 @@ def fetch_image(self, candidate, extra):
231232
message=u'downloading image')) as resp:
232233
ct = resp.headers.get('Content-Type', None)
233234
if ct not in CONTENT_TYPES:
234-
self._log.debug(
235-
u'not a supported image: {}',
236-
resp.headers.get('Content-Type') or u'no content type',
237-
)
235+
self._log.debug(u'not a supported image: {}',
236+
ct or u'no content type')
238237
candidate.path = None
239238
return
240239

241-
# Generate a temporary file with the correct extension.
242-
with NamedTemporaryFile(suffix=b'.' + CONTENT_TYPES[ct][0],
243-
delete=False) as fh:
244-
for chunk in resp.iter_content(chunk_size=1024):
240+
# Generate a temporary file and guess the extension based on
241+
# the Content-Type header. This may be wrong for badly
242+
# configured servers. E.g. fanart.tv only allows .jpg uploads
243+
# and ALWAYS returns a image/jpeg Content-Type, but other
244+
# formats with a erroneous .jp(e)g extension apparently can
245+
# sneak through the upload filter. Therefore validate the type
246+
# using the file magic.
247+
data = resp.iter_content(chunk_size=1024)
248+
try:
249+
chunk = next(data)
250+
except StopIteration:
251+
pass
252+
else:
253+
real_ct = _image_mime_type(chunk)
254+
ext = b'.' + CONTENT_TYPES[real_ct][0]
255+
if real_ct != ct:
256+
self._log.warn(u'Server specified {}, but returned a '
257+
u'{} image. Correcting the extension '
258+
u'to {}',
259+
ct, real_ct, ext)
260+
with NamedTemporaryFile(suffix=ext, delete=False) as fh:
245261
fh.write(chunk)
246-
self._log.debug(u'downloaded art to: {0}',
247-
util.displayable_path(fh.name))
248-
candidate.path = util.bytestring_path(fh.name)
262+
for chunk in data:
263+
fh.write(chunk)
264+
self._log.debug(u'downloaded art to: {0}',
265+
util.displayable_path(fh.name))
266+
candidate.path = util.bytestring_path(fh.name)
267+
249268
return
250269

251270
except (IOError, requests.RequestException, TypeError) as exc:

0 commit comments

Comments
 (0)