Skip to content

Commit

Permalink
Merge pull request #197 from kumattau/unexpected-corruption-check
Browse files Browse the repository at this point in the history
PR: Fix unexpected corruption check except for bundled fonts
  • Loading branch information
dalthviz authored Dec 22, 2021
2 parents 590a6ab + 71d12a5 commit ae9acfc
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 71 deletions.
6 changes: 3 additions & 3 deletions UPDATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ To update _Material Design Icons 6.x_, you must:
- download ttf from <https://raw.githubusercontent.com/Templarian/MaterialDesign-Webfont/master/fonts/materialdesignicons-webfont.ttf>
- regenerate the json charmap with the `materialdesignicons.css` file from <https://raw.githubusercontent.com/Templarian/MaterialDesign-Webfont/master/css/materialdesignicons.css>

The following script automatically download the last TTF font, generate the json charmap and display md5 hash of the TTF (to update iconic_font.py)
The following script automatically download the last TTF font, generate the json charmap and display md5 hash of the TTF (to update \_\_init__.py)

```Python
import re
Expand Down Expand Up @@ -95,7 +95,7 @@ To update _Phosphor_, you must:
- download ttf from <https://raw.githubusercontent.com/phosphor-icons/phosphor-icons/master/src/font/phosphor.ttf>
- regenerate the json charmap with the `phosphor.css` file from <https://raw.githubusercontent.com/phosphor-icons/phosphor-icons/master/src/css/phosphor.css>

The following script automatically download the last TTF font, generate the json charmap and display md5 hash of the TTF (to update iconic_font.py)
The following script automatically download the last TTF font, generate the json charmap and display md5 hash of the TTF (to update \_\_init__.py)

```Python
import re
Expand Down Expand Up @@ -148,7 +148,7 @@ To update _Remix Icon_, you must:
- download ttf from <https://raw.githubusercontent.com/Remix-Design/RemixIcon/master/fonts/remixicon.ttf>
- regenerate the json charmap with the `remixicon.css` file from <https://raw.githubusercontent.com/Remix-Design/RemixIcon/master/fonts/remixicon.css>

The following script automatically download the last TTF font, generate the json charmap and display md5 hash of the TTF (to update iconic_font.py)
The following script automatically download the last TTF font, generate the json charmap and display md5 hash of the TTF (to update \_\_init__.py)

```Python
import re
Expand Down
92 changes: 69 additions & 23 deletions qtawesome/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,70 @@
set_defaults
"""

import hashlib
import os

# Third party imports
from qtpy import QtCore, QtWidgets, QtGui

# Local imports
from ._version import __version__, version_info
from .animation import Pulse, Spin
from .iconic_font import IconicFont, set_global_defaults
from .iconic_font import IconicFont, set_global_defaults, FontError
from .iconic_font import SYSTEM_FONTS as _SYSTEM_FONTS
from .styles import dark, light

# Constants
_resource = { 'iconic': None }

_BUNDLED_FONTS = (
('fa',
'fontawesome4.7-webfont.ttf',
'fontawesome4.7-webfont-charmap.json'),
('fa5',
'fontawesome5-regular-webfont.ttf',
'fontawesome5-regular-webfont-charmap.json'),
('fa5s',
'fontawesome5-solid-webfont.ttf',
'fontawesome5-solid-webfont-charmap.json'),
('fa5b',
'fontawesome5-brands-webfont.ttf',
'fontawesome5-brands-webfont-charmap.json'),
('ei',
'elusiveicons-webfont.ttf',
'elusiveicons-webfont-charmap.json'),
('mdi',
'materialdesignicons5-webfont.ttf',
'materialdesignicons5-webfont-charmap.json'),
('mdi6',
'materialdesignicons6-webfont.ttf',
'materialdesignicons6-webfont-charmap.json'),
('ph',
'phosphor.ttf',
'phosphor-charmap.json'),
('ri',
'remixicon.ttf',
'remixicon-charmap.json'),
('msc',
'codicon.ttf',
'codicon-charmap.json'),
)


# MD5 Hashes for font files bundled with qtawesome:
_MD5_HASHES = {
'fontawesome4.7-webfont.ttf': 'b06871f281fee6b241d60582ae9369b9',
'fontawesome5-regular-webfont.ttf': '808833867034fb67a4a86dd2155e195d',
'fontawesome5-solid-webfont.ttf': '139654bb0acaba6b00ae30d5faf3d02f',
'fontawesome5-brands-webfont.ttf': '085b1dd8427dbeff10bd55410915a3f6',
'elusiveicons-webfont.ttf': '207966b04c032d5b873fd595a211582e',
'materialdesignicons5-webfont.ttf': 'b7d40e7ef80c1d4af6d94902af66e524',
'materialdesignicons6-webfont.ttf': '9a2f455e7cbce011368aee95d292613b',
'phosphor.ttf': '5b8dc57388b2d86243566b996cc3a789',
'remixicon.ttf': '888e61f04316f10bddfff7bee10c6dd0',
'codicon.ttf': 'ca2f9e22cee3a59156b3eded74d87784',
}


def has_valid_font_ids(inst):
"""Validate instance's font ids are loaded to QFontDatabase.
Expand Down Expand Up @@ -60,28 +112,22 @@ def _instance():
_resource['iconic'] = None

if _resource['iconic'] is None:
_resource['iconic'] = IconicFont(
('fa',
'fontawesome4.7-webfont.ttf',
'fontawesome4.7-webfont-charmap.json'),
('fa5',
'fontawesome5-regular-webfont.ttf',
'fontawesome5-regular-webfont-charmap.json'),
('fa5s',
'fontawesome5-solid-webfont.ttf',
'fontawesome5-solid-webfont-charmap.json'),
('fa5b',
'fontawesome5-brands-webfont.ttf',
'fontawesome5-brands-webfont-charmap.json'),
('ei', 'elusiveicons-webfont.ttf', 'elusiveicons-webfont-charmap.json'),
('mdi', 'materialdesignicons5-webfont.ttf',
'materialdesignicons5-webfont-charmap.json'),
('mdi6', 'materialdesignicons6-webfont.ttf',
'materialdesignicons6-webfont-charmap.json'),
('ph', 'phosphor.ttf', 'phosphor-charmap.json'),
('ri', 'remixicon.ttf', 'remixicon-charmap.json'),
('msc', 'codicon.ttf', 'codicon-charmap.json'),
)
# Verify that vendorized fonts are not corrupt
if not _SYSTEM_FONTS:
for fargs in _BUNDLED_FONTS:
ttf_filename = fargs[1]
ttf_hash = _MD5_HASHES.get(ttf_filename, None)
if ttf_hash is None:
continue
ttf_filepath = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"fonts", ttf_filename)
with open(ttf_filepath, "rb") as f:
ttf_calculated_hash_code = hashlib.md5(f.read()).hexdigest()
if ttf_calculated_hash_code != ttf_hash:
raise FontError(f"Font is corrupt at: '{ttf_filepath}'")

_resource['iconic'] = IconicFont(*_BUNDLED_FONTS)
return _resource['iconic']


Expand Down
29 changes: 0 additions & 29 deletions qtawesome/iconic_font.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

# Standard library imports
from __future__ import print_function
import hashlib
import json
import os
import warnings
Expand All @@ -30,20 +29,6 @@
# use system fonts
SYSTEM_FONTS = False

# MD5 Hashes for font files bundled with qtawesome:
MD5_HASHES = {
'fontawesome4.7-webfont.ttf': 'b06871f281fee6b241d60582ae9369b9',
'fontawesome5-regular-webfont.ttf': '808833867034fb67a4a86dd2155e195d',
'fontawesome5-solid-webfont.ttf': '139654bb0acaba6b00ae30d5faf3d02f',
'fontawesome5-brands-webfont.ttf': '085b1dd8427dbeff10bd55410915a3f6',
'elusiveicons-webfont.ttf': '207966b04c032d5b873fd595a211582e',
'materialdesignicons5-webfont.ttf': 'b7d40e7ef80c1d4af6d94902af66e524',
'materialdesignicons6-webfont.ttf': '9a2f455e7cbce011368aee95d292613b',
'phosphor.ttf': '5b8dc57388b2d86243566b996cc3a789',
'remixicon.ttf': '888e61f04316f10bddfff7bee10c6dd0',
'codicon.ttf': 'ca2f9e22cee3a59156b3eded74d87784',
}


def text_color():
try:
Expand Down Expand Up @@ -305,20 +290,6 @@ def hook(obj):
with open(os.path.join(directory, charmap_filename), 'r') as codes:
self.charmap[prefix] = json.load(codes, object_hook=hook)

# Verify that vendorized fonts are not corrupt
if not SYSTEM_FONTS:
ttf_hash = MD5_HASHES.get(ttf_filename, None)
if ttf_hash is not None:
hasher = hashlib.md5()
with open(os.path.join(directory, ttf_filename),
'rb') as f:
content = f.read()
hasher.update(content)
ttf_calculated_hash_code = hasher.hexdigest()
if ttf_calculated_hash_code != ttf_hash:
raise FontError(u"Font is corrupt at: '{0}'".format(
os.path.join(directory, ttf_filename)))

def icon(self, *names, **kwargs):
"""Return a QIcon object corresponding to the provided icon name."""
cache_key = '{}{}'.format(names,kwargs)
Expand Down
32 changes: 16 additions & 16 deletions setupbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import distutils.log

HERE = os.path.abspath(os.path.dirname(__file__))
ICONIC_FONT_PY_PATH = os.path.join(HERE, 'qtawesome', 'iconic_font.py')
INIT_PY_PATH = os.path.join(HERE, 'qtawesome', '__init__.py')


def rename_font(font_path, font_name):
Expand Down Expand Up @@ -209,21 +209,21 @@ def run(self):
# Store hashes for later:
hashes[style] = hashlib.md5(data).hexdigest()

# Now it's time to patch "iconic_font.py":
iconic_path = ICONIC_FONT_PY_PATH
self.__print('Patching new MD5 hashes in: %s' % iconic_path)
with open(iconic_path, 'r') as iconic_file:
contents = iconic_file.read()
# Now it's time to patch "__init__.py":
init_path = INIT_PY_PATH
self.__print('Patching new MD5 hashes in: %s' % init_path)
with open(init_path, 'r') as init_file:
contents = init_file.read()
# We read it in full, then use regex substitution:
for style, md5 in hashes.items():
self.__print('New "%s" hash is: %s' % (style, md5))
regex = r"('fontawesome5-%s-webfont.ttf':\s+)'(\w+)'" % style
subst = r"\g<1>'" + md5 + "'"
contents = re.sub(regex, subst, contents, 1)
# and finally overwrite with the modified file:
self.__print('Dumping updated file: %s' % iconic_path)
with open(iconic_path, 'w') as iconic_file:
iconic_file.write(contents)
self.__print('Dumping updated file: %s' % init_path)
with open(init_path, 'w') as init_file:
init_file.write(contents)

self.__print(
'\nFinished!\n'
Expand Down Expand Up @@ -295,16 +295,16 @@ def run(self):
md5 = hashlib.md5(data).hexdigest()
self.__print('New hash is: %s' % md5)

# Now it's time to patch "iconic_font.py":
self.__print('Patching new MD5 hashes in: %s' % ICONIC_FONT_PY_PATH)
with open(ICONIC_FONT_PY_PATH, 'r') as iconic_file:
contents = iconic_file.read()
# Now it's time to patch "__init__.py":
self.__print('Patching new MD5 hashes in: %s' % INIT_PY_PATH)
with open(INIT_PY_PATH, 'r') as init_file:
contents = init_file.read()
regex = r"('codicon.ttf':\s+)'(\w+)'"
subst = r"\g<1>'" + md5 + "'"
contents = re.sub(regex, subst, contents, 1)
self.__print('Dumping updated file: %s' % ICONIC_FONT_PY_PATH)
with open(ICONIC_FONT_PY_PATH, 'w') as iconic_file:
iconic_file.write(contents)
self.__print('Dumping updated file: %s' % INIT_PY_PATH)
with open(INIT_PY_PATH, 'w') as init_file:
init_file.write(contents)

self.__print(
'\nFinished!\n'
Expand Down

0 comments on commit ae9acfc

Please sign in to comment.