Update extlib/EXIF
Bump bundled EXIF lib to 1.0.10 as release in Sep 2012. Also skip unused detailed EXIF tags for reading, we might turn that on when we need them. Adapt test to wording change in EXIF Flas field and due to the fact that we use "details=False" by default now (we did not use these anyway) Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
This commit is contained in:
parent
89672855f1
commit
351fd95fff
274
mediagoblin/tests/#test_submission.py#
Normal file
274
mediagoblin/tests/#test_submission.py#
Normal file
@ -0,0 +1,274 @@
|
||||
# GNU MediaGoblin -- federated, autonomous media hosting
|
||||
# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
reload(sys)
|
||||
sys.setdefaultencoding('utf-8')
|
||||
|
||||
import urlparse
|
||||
import os
|
||||
|
||||
from nose.tools import assert_equal, assert_true
|
||||
from pkg_resources import resource_filename
|
||||
|
||||
from mediagoblin.tests.tools import get_test_app, \
|
||||
fixture_add_user
|
||||
from mediagoblin import mg_globals
|
||||
from mediagoblin.tools import template
|
||||
from mediagoblin.media_types.image import MEDIA_MANAGER as img_MEDIA_MANAGER
|
||||
|
||||
def resource(filename):
|
||||
return resource_filename('mediagoblin.tests', 'test_submission/' + filename)
|
||||
|
||||
|
||||
GOOD_JPG = resource('good.jpg')
|
||||
GOOD_PNG = resource('good.png')
|
||||
EVIL_FILE = resource('evil')
|
||||
EVIL_JPG = resource('evil.jpg')
|
||||
EVIL_PNG = resource('evil.png')
|
||||
BIG_BLUE = resource('bigblue.png')
|
||||
|
||||
GOOD_TAG_STRING = u'yin,yang'
|
||||
BAD_TAG_STRING = unicode('rage,' + 'f' * 26 + 'u' * 26)
|
||||
|
||||
FORM_CONTEXT = ['mediagoblin/submit/start.html', 'submit_form']
|
||||
REQUEST_CONTEXT = ['mediagoblin/user_pages/user.html', 'request']
|
||||
|
||||
|
||||
class TestSubmission:
|
||||
def setUp(self):
|
||||
self.test_app = get_test_app()
|
||||
|
||||
# TODO: Possibly abstract into a decorator like:
|
||||
# @as_authenticated_user('chris')
|
||||
test_user = fixture_add_user()
|
||||
|
||||
self.test_user = test_user
|
||||
|
||||
self.login()
|
||||
|
||||
def login(self):
|
||||
self.test_app.post(
|
||||
'/auth/login/', {
|
||||
'username': u'chris',
|
||||
'password': 'toast'})
|
||||
|
||||
def logout(self):
|
||||
self.test_app.get('/auth/logout/')
|
||||
|
||||
def do_post(self, data, *context_keys, **kwargs):
|
||||
url = kwargs.pop('url', '/submit/')
|
||||
do_follow = kwargs.pop('do_follow', False)
|
||||
template.clear_test_template_context()
|
||||
response = self.test_app.post(url, data, **kwargs)
|
||||
if do_follow:
|
||||
response.follow()
|
||||
context_data = template.TEMPLATE_TEST_CONTEXT
|
||||
for key in context_keys:
|
||||
context_data = context_data[key]
|
||||
return response, context_data
|
||||
|
||||
def upload_data(self, filename):
|
||||
return {'upload_files': [('file', filename)]}
|
||||
|
||||
def check_comments(self, request, media_id, count):
|
||||
comments = request.db.MediaComment.find({'media_entry': media_id})
|
||||
assert_equal(count, len(list(comments)))
|
||||
|
||||
def test_missing_fields(self):
|
||||
# Test blank form
|
||||
# ---------------
|
||||
response, form = self.do_post({}, *FORM_CONTEXT)
|
||||
assert_equal(form.file.errors, [u'You must provide a file.'])
|
||||
|
||||
# Test blank file
|
||||
# ---------------
|
||||
response, form = self.do_post({'title': u'test title'}, *FORM_CONTEXT)
|
||||
assert_equal(form.file.errors, [u'You must provide a file.'])
|
||||
|
||||
def check_url(self, response, path):
|
||||
assert_equal(urlparse.urlsplit(response.location)[2], path)
|
||||
|
||||
def check_normal_upload(self, title, filename):
|
||||
response, context = self.do_post({'title': title}, do_follow=True,
|
||||
**self.upload_data(filename))
|
||||
self.check_url(response, '/u/{0}/'.format(self.test_user.username))
|
||||
assert_true('mediagoblin/user_pages/user.html' in context)
|
||||
# Make sure the media view is at least reachable, logged in...
|
||||
url = '/u/{0}/m/{1}/'.format(self.test_user.username,
|
||||
title.lower().replace(' ', '-'))
|
||||
self.test_app.get(url)
|
||||
# ... and logged out too.
|
||||
self.logout()
|
||||
self.test_app.get(url)
|
||||
|
||||
def test_normal_jpg(self):
|
||||
self.check_normal_upload(u'Normal upload 1', GOOD_JPG)
|
||||
|
||||
def test_normal_png(self):
|
||||
self.check_normal_upload(u'Normal upload 2', GOOD_PNG)
|
||||
|
||||
def check_media(self, request, find_data, count=None):
|
||||
media = request.db.MediaEntry.find(find_data)
|
||||
if count is not None:
|
||||
assert_equal(media.count(), count)
|
||||
if count == 0:
|
||||
return
|
||||
return media[0]
|
||||
|
||||
def test_tags(self):
|
||||
# Good tag string
|
||||
# --------
|
||||
response, request = self.do_post({'title': u'Balanced Goblin',
|
||||
'tags': GOOD_TAG_STRING},
|
||||
*REQUEST_CONTEXT, do_follow=True,
|
||||
**self.upload_data(GOOD_JPG))
|
||||
media = self.check_media(request, {'title': u'Balanced Goblin'}, 1)
|
||||
assert media.tags[0]['name'] == u'yin'
|
||||
assert media.tags[0]['slug'] == u'yin'
|
||||
|
||||
assert media.tags[1]['name'] == u'yang'
|
||||
assert media.tags[1]['slug'] == u'yang'
|
||||
|
||||
# Test tags that are too long
|
||||
# ---------------
|
||||
response, form = self.do_post({'title': u'Balanced Goblin',
|
||||
'tags': BAD_TAG_STRING},
|
||||
*FORM_CONTEXT,
|
||||
**self.upload_data(GOOD_JPG))
|
||||
assert_equal(form.tags.errors, [
|
||||
u'Tags must be shorter than 50 characters. ' \
|
||||
'Tags that are too long: ' \
|
||||
'ffffffffffffffffffffffffffuuuuuuuuuuuuuuuuuuuuuuuuuu'])
|
||||
|
||||
def test_delete(self):
|
||||
response, request = self.do_post({'title': u'Balanced Goblin'},
|
||||
*REQUEST_CONTEXT, do_follow=True,
|
||||
**self.upload_data(GOOD_JPG))
|
||||
media = self.check_media(request, {'title': u'Balanced Goblin'}, 1)
|
||||
media_id = media.id
|
||||
|
||||
# Add a comment, so we can test for its deletion later.
|
||||
self.check_comments(request, media_id, 0)
|
||||
comment_url = request.urlgen(
|
||||
'mediagoblin.user_pages.media_post_comment',
|
||||
user=self.test_user.username, media=media_id)
|
||||
response = self.do_post({'comment_content': 'i love this test'},
|
||||
url=comment_url, do_follow=True)[0]
|
||||
self.check_comments(request, media_id, 1)
|
||||
|
||||
# Do not confirm deletion
|
||||
# ---------------------------------------------------
|
||||
delete_url = request.urlgen(
|
||||
'mediagoblin.user_pages.media_confirm_delete',
|
||||
user=self.test_user.username, media=media_id)
|
||||
# Empty data means don't confirm
|
||||
response = self.do_post({}, do_follow=True, url=delete_url)[0]
|
||||
media = self.check_media(request, {'title': u'Balanced Goblin'}, 1)
|
||||
media_id = media.id
|
||||
|
||||
# Confirm deletion
|
||||
# ---------------------------------------------------
|
||||
response, request = self.do_post({'confirm': 'y'}, *REQUEST_CONTEXT,
|
||||
do_follow=True, url=delete_url)
|
||||
self.check_media(request, {'id': media_id}, 0)
|
||||
self.check_comments(request, media_id, 0)
|
||||
|
||||
def test_evil_file(self):
|
||||
# Test non-suppoerted file with non-supported extension
|
||||
# -----------------------------------------------------
|
||||
response, form = self.do_post({'title': u'Malicious Upload 1'},
|
||||
*FORM_CONTEXT,
|
||||
**self.upload_data(EVIL_FILE))
|
||||
assert_equal(len(form.file.errors), 1)
|
||||
assert 'Sorry, I don\'t support that file type :(' == \
|
||||
str(form.file.errors[0])
|
||||
|
||||
|
||||
def test_get_media_manager(self):
|
||||
"""Test if the get_media_manger function returns sensible things
|
||||
"""
|
||||
response, request = self.do_post({'title': u'Balanced Goblin'},
|
||||
*REQUEST_CONTEXT, do_follow=True,
|
||||
**self.upload_data(GOOD_JPG))
|
||||
media = self.check_media(request, {'title': u'Balanced Goblin'}, 1)
|
||||
|
||||
assert_equal(media.media_type, u'mediagoblin.media_types.image')
|
||||
assert_equal(media.media_manager, img_MEDIA_MANAGER)
|
||||
|
||||
|
||||
def test_sniffing(self):
|
||||
'''
|
||||
Test sniffing mechanism to assert that regular uploads work as intended
|
||||
'''
|
||||
template.clear_test_template_context()
|
||||
response = self.test_app.post(
|
||||
'/submit/', {
|
||||
'title': u'UNIQUE_TITLE_PLS_DONT_CREATE_OTHER_MEDIA_WITH_THIS_TITLE'
|
||||
}, upload_files=[(
|
||||
'file', GOOD_JPG)])
|
||||
|
||||
response.follow()
|
||||
|
||||
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/user_pages/user.html']
|
||||
|
||||
request = context['request']
|
||||
|
||||
media = request.db.MediaEntry.find_one({
|
||||
u'title': u'UNIQUE_TITLE_PLS_DONT_CREATE_OTHER_MEDIA_WITH_THIS_TITLE'})
|
||||
|
||||
assert media.media_type == 'mediagoblin.media_types.image'
|
||||
|
||||
def check_false_image(self, title, filename):
|
||||
# NOTE: The following 2 tests will ultimately fail, but they
|
||||
# *will* pass the initial form submission step. Instead,
|
||||
# they'll be caught as failures during the processing step.
|
||||
response, context = self.do_post({'title': title}, do_follow=True,
|
||||
**self.upload_data(filename))
|
||||
self.check_url(response, '/u/{0}/'.format(self.test_user.username))
|
||||
entry = mg_globals.database.MediaEntry.find_one({'title': title})
|
||||
assert_equal(entry.state, 'failed')
|
||||
assert_equal(entry.fail_error, u'mediagoblin.processing:BadMediaFail')
|
||||
|
||||
def test_evil_jpg(self):
|
||||
# Test non-supported file with .jpg extension
|
||||
# -------------------------------------------
|
||||
self.check_false_image(u'Malicious Upload 2', EVIL_JPG)
|
||||
|
||||
def test_evil_png(self):
|
||||
# Test non-supported file with .png extension
|
||||
# -------------------------------------------
|
||||
self.check_false_image(u'Malicious Upload 3', EVIL_PNG)
|
||||
|
||||
def test_processing(self):
|
||||
data = {'title': u'Big Blue'}
|
||||
response, request = self.do_post(data, *REQUEST_CONTEXT, do_follow=True,
|
||||
**self.upload_data(BIG_BLUE))
|
||||
media = self.check_media(request, data, 1)
|
||||
last_size = 1024 ** 3 # Needs to be larger than bigblue.png
|
||||
for key, basename in (('original', 'bigblue.png'),
|
||||
('medium', 'bigblue.medium.png'),
|
||||
('thumb', 'bigblue.thumbnail.png')):
|
||||
# Does the processed image have a good filename?
|
||||
filename = resource_filename(
|
||||
'mediagoblin.tests',
|
||||
os.path.join('test_user_dev/media/public',
|
||||
*media.media_files.get(key, [])))
|
||||
assert_true(filename.endswith('_' + basename))
|
||||
# Is it smaller than the last processed image we looked at?
|
||||
size = os.stat(filename).st_size
|
||||
assert_true(last_size > size)
|
||||
last_size = size
|
1
mediagoblin/tests/.#test_submission.py
Symbolic link
1
mediagoblin/tests/.#test_submission.py
Symbolic link
@ -0,0 +1 @@
|
||||
spaetz@spaetzBookPro.5549:1356294438
|
@ -58,10 +58,10 @@ def test_exif_extraction():
|
||||
gps = get_gps_data(result)
|
||||
|
||||
# Do we have the result?
|
||||
assert len(result) == 108
|
||||
assert len(result) == 56
|
||||
|
||||
# Do we have clean data?
|
||||
assert len(clean) == 105
|
||||
assert len(clean) == 53
|
||||
|
||||
# GPS data?
|
||||
assert gps == {}
|
||||
@ -70,7 +70,7 @@ def test_exif_extraction():
|
||||
assert useful == {
|
||||
'EXIF Flash': {
|
||||
'field_type': 3,
|
||||
'printable': 'No',
|
||||
'printable': u'Flash did not fire',
|
||||
'field_offset': 380,
|
||||
'tag': 37385,
|
||||
'values': [0],
|
||||
@ -123,18 +123,7 @@ def test_exif_extraction():
|
||||
'field_offset': 708,
|
||||
'tag': 33437,
|
||||
'values': [[10, 1]],
|
||||
'field_length': 8},
|
||||
'EXIF UserComment': {
|
||||
'field_type': 7,
|
||||
'printable': 'Joar Wandborg ',
|
||||
'field_offset': 26180,
|
||||
'tag': 37510,
|
||||
'values': [
|
||||
65, 83, 67, 73, 73, 0, 0, 0, 74, 111, 97, 114, 32, 87,
|
||||
97, 110, 100, 98, 111, 114, 103, 32, 32, 32, 32, 32, 32,
|
||||
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
|
||||
32, 32, 32],
|
||||
'field_length': 44}}
|
||||
'field_length': 8}}
|
||||
|
||||
|
||||
def test_exif_image_orientation():
|
||||
|
@ -73,7 +73,7 @@ def extract_exif(filename):
|
||||
|
||||
try:
|
||||
image = open(filename)
|
||||
exif_tags = process_file(image)
|
||||
exif_tags = process_file(image, details=False)
|
||||
except IOError:
|
||||
raise BadMediaFail(_('Could not read the image file.'))
|
||||
|
||||
@ -97,7 +97,6 @@ def clean_exif(exif):
|
||||
for key, value in exif.items():
|
||||
if not key in disabled_tags:
|
||||
clean_exif[key] = _ifd_tag_to_dict(value)
|
||||
|
||||
return clean_exif
|
||||
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
../../../extlib/exif/EXIF.py
|
1790
mediagoblin/tools/extlib/EXIF.py
Executable file
1790
mediagoblin/tools/extlib/EXIF.py
Executable file
File diff suppressed because it is too large
Load Diff
126
mediagoblin/tools/extlib/changes.txt
Normal file
126
mediagoblin/tools/extlib/changes.txt
Normal file
@ -0,0 +1,126 @@
|
||||
~ EXIF.py Changelog ~
|
||||
|
||||
2012-09-26 - Ianaré Sévi
|
||||
Merge patches:
|
||||
Add GPS tags
|
||||
Add better endian debug info
|
||||
|
||||
2012-06-13 - Ianaré Sévi
|
||||
Merge patches:
|
||||
Support malformed last IFD by fhats
|
||||
Light source, Flash and Metering mode dictionaries update by gryfik
|
||||
|
||||
2008-07-31 - Ianaré Sévi
|
||||
Wikipedia Commons hunt for suitable test case images,
|
||||
testing new code additions.
|
||||
|
||||
2008-07-09 - Stephen H. Olson
|
||||
Fix a problem with reading MakerNotes out of NEF files.
|
||||
Add some more Nikon MakerNote tags.
|
||||
|
||||
2008-07-08 - Stephen H. Olson
|
||||
An error check for large tags totally borked MakerNotes.
|
||||
With Nikon anyway, valid MakerNotes can be pretty big.
|
||||
Add error check for a crash caused by nikon_ev_bias being
|
||||
called with the wrong args.
|
||||
Drop any garbage after a null character in string
|
||||
(patch from Andrew McNabb <amcnabb@google.com>).
|
||||
|
||||
2008-02-12 - Ianaré Sévi
|
||||
Fix crash on invalid MakerNote
|
||||
Fix crash on huge Makernote (temp fix)
|
||||
Add printIM tag 0xC4A5, needs decoding info
|
||||
Add 0x9C9B-F range of tags
|
||||
Add a bunch of tag definitions from:
|
||||
http://owl.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html
|
||||
Add 'strict' variable and command line option
|
||||
|
||||
2008-01-18 - Gunter Ohrner
|
||||
Add 'GPSDate' tag
|
||||
|
||||
2007-12-12 - Ianaré Sévi
|
||||
Fix quick option on certain image types
|
||||
Add note on tag naming in documentation
|
||||
|
||||
2007-11-30 - Ianaré Sévi
|
||||
Changed -s option to -t
|
||||
Put changelog into separate file
|
||||
|
||||
2007-10-28 - Ianaré Sévi
|
||||
Merged changes from MoinMoin:ReimarBauer
|
||||
Added command line option for debug, stop
|
||||
processing on tag.
|
||||
|
||||
2007-09-27 - Ianaré Sévi
|
||||
Add some Olympus Makernote tags.
|
||||
|
||||
2007-09-26 - Stephen H. Olson
|
||||
Don't error out on invalid Olympus 'SpecialMode'.
|
||||
Add a few more Olympus/Minolta tags.
|
||||
|
||||
2007-09-22 - Stephen H. Olson
|
||||
Don't error on invalid string
|
||||
Improved Nikon MakerNote support
|
||||
|
||||
2007-05-03 - Martin Stone <mj_stone@users.sourceforge.net>
|
||||
Fix for inverted detailed flag and Photoshop header
|
||||
|
||||
2007-03-24 - Ianaré Sévi
|
||||
Can now ignore MakerNotes Tags for faster processing.
|
||||
|
||||
2007-01-18 - Ianaré Sévi <ianare@gmail.com>
|
||||
Fixed a couple errors and assuming maintenance of the library.
|
||||
|
||||
2006-08-04 MoinMoin:ReimarBauer
|
||||
Added an optional parameter name to process_file and dump_IFD. Using this parameter the
|
||||
loop is breaked after that tag_name is processed.
|
||||
some PEP8 changes
|
||||
|
||||
---------------------------- original notices -------------------------
|
||||
|
||||
Contains code from "exifdump.py" originally written by Thierry Bousch
|
||||
<bousch@topo.math.u-psud.fr> and released into the public domain.
|
||||
|
||||
Updated and turned into general-purpose library by Gene Cash
|
||||
|
||||
Patch Contributors:
|
||||
* Simon J. Gerraty <sjg@crufty.net>
|
||||
s2n fix & orientation decode
|
||||
* John T. Riedl <riedl@cs.umn.edu>
|
||||
Added support for newer Nikon type 3 Makernote format for D70 and some
|
||||
other Nikon cameras.
|
||||
* Joerg Schaefer <schaeferj@gmx.net>
|
||||
Fixed subtle bug when faking an EXIF header, which affected maker notes
|
||||
using relative offsets, and a fix for Nikon D100.
|
||||
|
||||
1999-08-21 TB Last update by Thierry Bousch to his code.
|
||||
|
||||
2002-01-17 CEC Discovered code on web.
|
||||
Commented everything.
|
||||
Made small code improvements.
|
||||
Reformatted for readability.
|
||||
|
||||
2002-01-19 CEC Added ability to read TIFFs and JFIF-format JPEGs.
|
||||
Added ability to extract JPEG formatted thumbnail.
|
||||
Added ability to read GPS IFD (not tested).
|
||||
Converted IFD data structure to dictionaries indexed by
|
||||
tag name.
|
||||
Factored into library returning dictionary of IFDs plus
|
||||
thumbnail, if any.
|
||||
|
||||
2002-01-20 CEC Added MakerNote processing logic.
|
||||
Added Olympus MakerNote.
|
||||
Converted data structure to single-level dictionary, avoiding
|
||||
tag name collisions by prefixing with IFD name. This makes
|
||||
it much easier to use.
|
||||
2002-01-23 CEC Trimmed nulls from end of string values.
|
||||
|
||||
2002-01-25 CEC Discovered JPEG thumbnail in Olympus TIFF MakerNote.
|
||||
|
||||
2002-01-26 CEC Added ability to extract TIFF thumbnails.
|
||||
Added Nikon, Fujifilm, Casio MakerNotes.
|
||||
|
||||
2003-11-30 CEC Fixed problem with canon_decode_tag() not creating an
|
||||
IFD_Tag() object.
|
||||
|
||||
2004-02-15 CEC Finally fixed bit shift warning by converting Y to 0L.
|
Loading…
x
Reference in New Issue
Block a user