Allow web-accessible file references in media objects

Gedcom 7.0 allows an URL with scheme ftp, http, or https in
the FILE tag.

See:

https://gedcom.io/specifications/FamilySearchGEDCOMv7.html#FILE
This commit is contained in:
Nick Hall 2021-06-10 14:33:00 +01:00
parent b41969c4c2
commit 55a6ad0b6b
5 changed files with 62 additions and 29 deletions

View File

@ -33,6 +33,7 @@ _type_map = {
'image/png' : 'PNG image',
'application/pdf' : 'PDF document',
'text/rtf' : 'Rich Text File',
'text/html' : 'Web page',
}
mimetypes.add_type('application/x-gramps','.grdb')

View File

@ -202,6 +202,8 @@ def media_path_full(db, filename):
Given a database and a filename of a media, return the media filename
is full form, eg 'graves/tomb.png' becomes '/home/me/genea/graves/tomb.png
"""
if filename.startswith(("http://", "https://", "ftp://")):
return filename
if os.path.isabs(filename):
return filename
mpath = media_path(db)

View File

@ -243,7 +243,10 @@ def get_thumbnail_path(src_file, mtype=None, rectangle=None, size=SIZE_NORMAL):
"""
filename = __build_thumb_path(src_file, rectangle, size)
if not os.path.isfile(src_file):
return os.path.join(IMAGE_DIR, "image-missing.png")
if src_file.startswith(("http://", "https://", "ftp://")):
return os.path.join(IMAGE_DIR, "gramps-url.png")
else:
return os.path.join(IMAGE_DIR, "image-missing.png")
else:
if (not os.path.isfile(filename)) or (
os.path.getmtime(src_file) > os.path.getmtime(filename)):

View File

@ -27,6 +27,9 @@
#
#-------------------------------------------------------------------------
import os
from urllib.request import urlopen, Request
from urllib.error import HTTPError
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
@ -307,18 +310,43 @@ class EditMedia(EditPrimary):
return
path = self.file_path.get_text()
full_path = media_path_full(self.db, path)
if os.path.isfile(full_path):
self.determine_mime()
if path.startswith(("http://", "https://", "ftp://")):
request = Request(path, headers={'User-Agent': 'Mozilla/5.0'})
try:
response = urlopen(request)
status = response.status
reason = response.reason
except HTTPError as error:
status = error.code
reason = error.reason
if status == 200:
mime_type = response.getheader('Content-Type', default='')
offset = mime_type.find(';')
if offset != -1:
mime_type = mime_type[:offset]
self.obj.set_mime_type(mime_type)
else:
msg1 = _("Invalid url!")
msg2 = _("The url '{url}' is not valid.\n"
"Error: {error}").format(url=path, error=reason)
ErrorDialog(msg1, msg2, parent=self.window)
self.ok_button.set_sensitive(True)
return
else:
msg1 = _("There is no media matching the current path value!")
msg2 = _("You have attempted to use the path with "
"value '%(path)s'. This path does not exist!"
" Please enter a different path") % {
'path' : path }
ErrorDialog(msg1, msg2, parent=self.window)
self.ok_button.set_sensitive(True)
return
full_path = media_path_full(self.db, path)
if os.path.isfile(full_path):
self.determine_mime()
else:
msg1 = _("There is no media matching the current path value!")
msg2 = _("You have attempted to use the path with "
"value '%(path)s'. This path does not exist!"
" Please enter a different path") % {
'path' : path }
ErrorDialog(msg1, msg2, parent=self.window)
self.ok_button.set_sensitive(True)
return
self.obj.set_path(path)

View File

@ -395,28 +395,27 @@ def open_file_with_default_application(path, uistate):
:type file_path: string
:return: nothing
"""
norm_path = os.path.normpath(path)
if not os.path.exists(norm_path):
display_error_dialog(0, _("File %s does not exist") % norm_path,
uistate)
return
if path.startswith(("http://", "https://", "ftp://")):
norm_path = path
else:
norm_path = os.path.normpath(path)
if not os.path.exists(norm_path):
display_error_dialog(0, _("File %s does not exist") % norm_path,
uistate)
return
if win():
try:
os.startfile(norm_path)
except WindowsError as msg:
display_error_dialog(0, str(msg),
uistate)
return
if not norm_path.startswith('file://'):
norm_path = 'file://' + norm_path
try:
Gio.AppInfo.launch_default_for_uri(norm_path)
except GLib.Error as error:
display_error_dialog(0, str(error), uistate)
display_error_dialog(0, str(msg), uistate)
else:
if not norm_path.startswith(("http://", "https://", "ftp://", "file://")):
norm_path = 'file://' + norm_path
try:
Gio.AppInfo.launch_default_for_uri(norm_path)
except GLib.Error as error:
display_error_dialog(0, str(error), uistate)
def process_pending_events(max_count=20):
"""