Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from pathlib import Path
import config
from icon_theme_cache import read_icon_cache

ICON_SIZE = 48

Expand Down Expand Up @@ -718,13 +719,7 @@ def refresh_chooser(self, chooser, path_suffix, themes, callback):
else:
read_path = '/usr/share/cinnamon/cinnamon-settings/icons'

icon_paths = {}
with open(read_path, 'r') as cache_file:
for line in cache_file:
theme_name, icon_path = line.strip().split(':')
icon_paths[theme_name] = icon_path

dump = False
icon_paths, dump = read_icon_cache(read_path)

# Collect all themes with their categories and variants
categorized_themes = []
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
def read_icon_cache(path):
"""Read valid theme icon entries and report whether the cache was damaged."""
icon_paths = {}
damaged = False

with open(path, "r", encoding="utf-8", errors="replace") as cache_file:
for line in cache_file:
entry = line.strip()
if "\ufffd" in entry or any(ord(char) < 32 or ord(char) == 127 for char in entry):
damaged = True
continue

if ":" not in entry:
damaged = True
continue

theme_name, icon_path = entry.split(":", 1)
if not theme_name or not icon_path:
damaged = True
continue

icon_paths[theme_name] = icon_path

return icon_paths, damaged
52 changes: 52 additions & 0 deletions tests/test_icon_theme_cache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import sys
import tempfile
import unittest
from pathlib import Path

MODULES = (
Path(__file__).resolve().parents[1]
/ "files/usr/share/cinnamon/cinnamon-settings/modules"
)
sys.path.insert(0, str(MODULES))

from icon_theme_cache import read_icon_cache


class ReadIconCacheTest(unittest.TestCase):
def test_skips_corrupt_lines_and_preserves_colons_in_paths(self):
with tempfile.TemporaryDirectory() as temp_dir:
cache = Path(temp_dir) / "icons"
cache.write_bytes(
b"valid:icons/valid.png\n"
b"missing-separator\n"
b"\xffinvalid:icons/invalid.png\n"
b"binary\x00theme:icons/binary.png\n"
b"colon:path:with:colons.png\n"
b":missing-name\n"
b"empty-path:\n"
)

icon_paths, damaged = read_icon_cache(cache)

self.assertTrue(damaged)
self.assertEqual(
icon_paths,
{
"valid": "icons/valid.png",
"colon": "path:with:colons.png",
},
)

def test_valid_cache_is_not_marked_damaged(self):
with tempfile.TemporaryDirectory() as temp_dir:
cache = Path(temp_dir) / "icons"
cache.write_text("theme:icons/folder.svg\n", encoding="utf-8")

icon_paths, damaged = read_icon_cache(cache)

self.assertFalse(damaged)
self.assertEqual(icon_paths, {"theme": "icons/folder.svg"})


if __name__ == "__main__":
unittest.main()
Loading