3eeead863e529b7a4633b6df3f2fd5eefc1c10d6
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 from mediagoblin
.tools
.pluginapi
import hook_handle
23 from mediagoblin
.tools
.translate
import lazy_pass_to_ugettext
as _
25 _log
= logging
.getLogger(__name__
)
28 class FileTypeNotSupported(Exception):
32 class TypeNotFound(FileTypeNotSupported
):
33 '''Raised if no mediagoblin plugin supporting this file type was found'''
37 class MissingComponents(FileTypeNotSupported
):
38 '''Raised if plugin found, but it can't process the file for some reason'''
42 class MediaManagerBase(object):
43 "Base class for all media managers"
45 # Please override in actual media managers
46 media_fetch_order
= None
49 def sniff_handler(*args
, **kwargs
):
52 def __init__(self
, entry
):
55 def __getitem__(self
, i
):
56 return getattr(self
, i
)
58 def __contains__(self
, i
):
59 return hasattr(self
, i
)
62 def sniff_media_contents(media_file
, filename
):
64 Check media contents using 'expensive' scanning. For example, for video it
65 is checking the contents using gstreamer
66 :param media_file: file-like object with 'name' attribute
67 :param filename: expected filename of the media
69 media_type
= hook_handle('sniff_handler', media_file
, filename
)
71 _log
.info('{0} accepts the file'.format(media_type
))
72 return media_type
, hook_handle(('media_manager', media_type
))
74 _log
.debug('{0} did not accept the file'.format(media_type
))
75 raise FileTypeNotSupported(
76 # TODO: Provide information on which file types are supported
77 _(u
'Sorry, I don\'t support that file type :('))
79 def get_media_type_and_manager(filename
):
81 Try to find the media type based on the file name, extension
82 specifically. This is used as a speedup, the sniffing functionality
83 then falls back on more in-depth bitsniffing of the source file.
85 This hook is deprecated, 'type_match_handler' should be used instead
87 if filename
.find('.') > 0:
88 # Get the file extension
89 ext
= os
.path
.splitext(filename
)[1].lower()
91 # Omit the dot from the extension and match it against
93 if hook_handle('get_media_type_and_manager', ext
[1:]):
94 return hook_handle('get_media_type_and_manager', ext
[1:])
96 _log
.info('File {0} has no file extension, let\'s hope the sniffers get it.'.format(
100 _(u
'Sorry, I don\'t support that file type :('))
102 def type_match_handler(media_file
, filename
):
103 '''Check media file by name and then by content
105 Try to find the media type based on the file name, extension
106 specifically. After that, if media type is one of supported ones, check the
109 if filename
.find('.') > 0:
110 # Get the file extension
111 ext
= os
.path
.splitext(filename
)[1].lower()
113 # Omit the dot from the extension and match it against
115 hook_result
= hook_handle('type_match_handler', ext
[1:])
117 _log
.info('Info about file found, checking further')
118 MEDIA_TYPE
, Manager
, sniffer
= hook_result
120 _log
.debug('sniffer is None, plugin trusts the extension')
121 return MEDIA_TYPE
, Manager
122 _log
.info('checking the contents with sniffer')
125 _log
.info('checked, found')
126 return MEDIA_TYPE
, Manager
127 except Exception as e
:
128 _log
.info('sniffer says it will not accept the file')
132 _log
.info('No plugins handled extension {0}'.format(ext
))
134 _log
.info('File {0} has no known file extension, let\'s hope '
135 'the sniffers get it.'.format(filename
))
136 raise TypeNotFound(_(u
'Sorry, I don\'t support that file type :('))
139 def sniff_media(media_file
, filename
):
141 Iterate through the enabled media types and find those suited
144 # copy the contents to a .name-enabled temporary file for further checks
145 # TODO: there are cases when copying is not required
146 tmp_media_file
= tempfile
.NamedTemporaryFile()
147 shutil
.copyfileobj(media_file
, tmp_media_file
)
150 return type_match_handler(tmp_media_file
, filename
)
151 except TypeNotFound
as e
:
152 _log
.info('No plugins using two-step checking found')
154 # keep trying, using old `get_media_type_and_manager`
156 return get_media_type_and_manager(filename
)
157 except TypeNotFound
as e
:
158 # again, no luck. Do it expensive way
159 _log
.info('No media handler found by file extension')
160 _log
.info('Doing it the expensive way...')
161 return sniff_media_contents(tmp_media_file
, filename
)